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

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

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
> 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).


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 Mas i Hernāndez - Mono development team - http://www.mono-project.com
Homepage and LiveJournal at http://www.softcatala.org/~jmas

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)