none
GDI leak in old Win32 code RRS feed

  • Question

  • This is really very old Win32 code from Charles Petzold's "Programming Windows":

    You might want to create pens on the fly and combine the CreatePen and SelectObject calls in the same statement:

    SelectObject (hdc, CreatePen (PS_DASH, 0, RGB (255, 0, 0))) ;
    

    Now when you draw lines, you'll be using a red dashed pen. When you're finished drawing the red dashed lines, you can delete the pen. Whoops! How can you delete the pen when you haven't saved the pen handle? Recall that SelectObject returns the handle to the pen previously selected in the device context. This means that you can delete the pen by selecting the stock BLACK_PEN into the device context and deleting the value returned from SelectObject:

    DeleteObject (SelectObject (hdc, GetStockObject (BLACK_PEN))) ;

    This is found to be leaking the Pen handle. Are there recent changes to do with the object created on the fly which get leaked now?

    Wednesday, December 4, 2019 3:21 AM

Answers

All replies

  • Hello,

    according to the documentation https://docs.microsoft.com/en-us/windows/win32/api/wingdi/nf-wingdi-createpen you must DeleteObject of the pen when you don't need it anymore. SelectObject can return NULL, so if it returns NULL, your pen is not deleted.

    You should use a variable to hold the pen.

    HPEN hPen;
    hPen = CreatePen(PS_DASH, 0, RGB (255, 0, 0));
    SelectObject(hdc, hPen);
    
    ...
    
    DeleteObject(hPen);
    

    Regards, Guido

    • Marked as answer by Wayne W1 Sunday, December 8, 2019 8:14 PM
    Wednesday, December 4, 2019 7:09 AM
  • That sequence does work, but only if you do not select any other pens in between.

    Tim Roberts | Driver MVP Emeritus | Providenza & Boekelheide, Inc.

    Wednesday, December 4, 2019 7:39 AM
  • "Do not delete a drawing object (pen or brush) while it is still selected into a DC."

    See: https://docs.microsoft.com/en-us/windows/win32/api/wingdi/nf-wingdi-deleteobject

    Wednesday, December 4, 2019 9:03 AM
  • Yeah, the posted code was taken from Charles' 'Programming Windows' book and also in some MSDN sample code. The code has been used for decades. It's only recently we noticed the leak and we have to change the code to:

    HPEN hNewPen = CreatePen (PS_DASH, 0, RGB (255, 0, 0));

    hOldPen = SelectObject (hdc, hNewPen);

    ...

    SelectObject(hdc, hOldPen);

    DeleteObject(hNewPen);

    This works and stopped the leak. We are trying to understand what's happening.

    Was it always leaking, or Windows has changed behaviour to these Gdi objects created on the fly?

    Thursday, December 5, 2019 1:05 AM
  • Yeah, the posted code was taken from Charles' 'Programming Windows' book and also in some MSDN sample code. The code has been used for decades. It's only recently we noticed the leak and we have to change the code to:

    HPEN hNewPen = CreatePen (PS_DASH, 0, RGB (255, 0, 0));

    hOldPen = SelectObject (hdc, hNewPen);

    ...

    SelectObject(hdc, hOldPen);

    DeleteObject(hNewPen);

    This works and stopped the leak. We are trying to understand what's happening.

    Was it always leaking, or Windows has changed behaviour to these Gdi objects created on the fly?

    As far as I know, Windows has not changed the behaviour to these Gdi objects. Maybe something happens in the code "…" (that you don't show). SelectObject still can return NULL, too. Do not assume that a programming book is the all-known bible for programming. If you still want to know what's happening, you could for example compare the result of Select(hdc, hOldPen) with hNewPen and check if there is a memory leak when both values are the same (if they are not the same, there will be a leak of course).
    Thursday, December 5, 2019 7:51 AM
  • Thanks, that's it. SelectObject was returning null. It happens when the DC was from CreateMetaFile and if you select a pen from ExtCreatePen.

    For best practice, a local variable should be used to hold the pen and delete it afterwards.

    Sunday, December 8, 2019 8:20 PM