Al Berger
Al Berger

Reputation: 1068

What in this code causes memory leak in C#?

In the Windows Task Manager I discovered that memory usage of my program is increases over time while it's running. The memory leak is caused by the code below. The code is a loop iterating over a list of images and resizes them according to code example in MSDN. All resources seem to be managed and are freed with .Dispose().

foreach ( string file in files )
{
    image = Image.FromFile( file );

    Rectangle cropRect = new Rectangle( 0, 0, 1000, 1000 );
    Bitmap src = ( Bitmap ) image;
    Bitmap target = new Bitmap( cropRect.Width, cropRect.Height );

    using ( Graphics g = Graphics.FromImage( target ) )  
    {
        g.DrawImage( src, new Rectangle( 0, 0, target.Width, target.Height ),
                                        cropRect,
                                        GraphicsUnit.Pixel );
    }

    image.Dispose();
    image = Image.FromHbitmap( target.GetHbitmap() );
    src.Dispose();
    target.Dispose();
    image.Dispose();
}

Could someone advise please what can be the cause of the memory leak in this code?

Upvotes: 2

Views: 188

Answers (1)

Lucas Trzesniewski
Lucas Trzesniewski

Reputation: 51330

From the docs of GetHbitmap:

You are responsible for calling the GDI DeleteObject method to free the memory used by the GDI bitmap object. For more information about GDI bitmaps, see Bitmaps in the Windows GDI documentation.

Then, from the docs of FromHbitmap:

The FromHbitmap method makes a copy of the GDI bitmap; so you can release the incoming GDI bitmap using the GDI DeleteObject method immediately after creating the new Image.

Seems pretty clear... You need to call DeleteObject:

[DllImport("gdi32.dll")]
private static extern bool DeleteObject(IntPtr hObject);

As SJoshi points out, you should use using blocks to ensure Dispose is called in case of exception. The DeleteObject call should be inside a finally block to get the same effect.

Upvotes: 9

Related Questions