[Mono-winforms-list] Matrix memory management in GDI+ bug

Jordi Mas jordi@ximian.com
Sat, 12 Mar 2005 17:41:03 +0100


--=-6r+UoCdO/IseuQcFdbQN
Content-Type: text/plain; charset=ISO-8859-1
Content-Transfer-Encoding: 8bit

El ds 12 de 03 del 2005 a les 11:18 +0100, en/na Laurent Debacker va
escriure:
> Hi,
> 
> There's is a bug in the way mono manage the unmanaged matrix in libgdiplus.
> 
> What I wanted to do is to save the transform matrix used in a Graphics
> object, save it in a global variable to reuse it later in other
> Graphics objects. It's just for optimization purpose.
> 
> However Mono's System.Drawing.Drawing2D.Matrix doesn't behave like
> Microsoft's one.
> 
> With Microsoft I can take the transform matrix from a matrix, even
> Dispose() it, then give it to another Graphics object, and it still
> works. I know it's tricky to Dispose() there, but I wanted to do
> futher research.
> 
> In Mono, Matrix.Dipose() (see source code
> http://svn.myrealbox.com/viewcvs/trunk/mcs/class/System.Drawing/System.Drawing.Drawing2D/Matrix.cs?rev=31166&view=auto
>  just always call GdipDeleteMatrix in libgdiplus
> (http://svn.myrealbox.com/viewcvs/trunk/libgdiplus/src/matrix.c?rev=39075&view=auto),
> which in turn calls cairo_matrix_destroy
> (http://svn.myrealbox.com/viewcvs/trunk/libgdiplus/cairo/src/cairo_matrix.c?rev=39488&view=auto),
> which simply do a free().
> 
> So your implementation is logic, but isn't compatible with Microsoft's one.
> 
> I would recommand you to call GdipDeleteMatrix in the destructor of
> System.Drawing.Drawing2D.Matrix, and leave Dipose() empty. That way as
> long as the managed Matrix lives, the unmanaged one will also.
> 
> The error message I got with my code was "mono in free(): error: chunk
> is already free" under FreeBSD 5.3-RELEASE, and libgdiplus-devel,
> mono-devel (1.1.4) from the BSD# project
> (http://forge.novell.com/modules/xfmod/project/?bsd-sharp).

Laurent,

If you call Dispose the resource should be freed, as users will expect.
Also, Microsoft does works this way.

Attached you have a patch that fixes our Dispose method. Please, if this
still do not work for you, send me the sample and I'll look into it.

Thanks for your feedback Laurent,

Jordi,

-- 
Jordi Mas i Hernāndez - Mono development team - http://www.mono-project.com
Homepage and LiveJournal at http://www.softcatala.org/~jmas


--=-6r+UoCdO/IseuQcFdbQN
Content-Disposition: attachment; filename=matrix.diff
Content-Type: text/x-patch; name=matrix.diff; charset=ISO-8859-1
Content-Transfer-Encoding: 7bit

Index: Matrix.cs
===================================================================
--- Matrix.cs	(revision 41526)
+++ Matrix.cs	(working copy)
@@ -131,8 +131,13 @@
         
                 public void Dispose ()
                 {
-			Status status = GDIPlus.GdipDeleteMatrix (nativeMatrix);
-			GDIPlus.CheckStatus (status);
+			if (nativeMatrix != IntPtr.Zero) {
+				Status status = GDIPlus.GdipDeleteMatrix (nativeMatrix);
+				GDIPlus.CheckStatus (status);
+				nativeMatrix = IntPtr.Zero;
+			}
+
+			GC.SuppressFinalize (true);
                 }                       
         
                 public override bool Equals (object obj)

--=-6r+UoCdO/IseuQcFdbQN--