'Can't release HBITMAP, memory leaking using CreateDIBitmap

I am using CreateDIBitmap() and always realeasing it by DeleteObject(). I am using it when my slider is moving and I noticed that memory used is increasing every time.

This is my function that creating HBITMAP from indexed bitmap data:

HBITMAP APP_Make_HBITMAP_From_Bitmap_Indexed(int _width, int _height, u_int32* _table_ptr, u_int8* _index_ptr)
{
    // window bitamp structure - to use with window API
    struct sAPP_Windows_Bitmap
    {
        BITMAPINFOHEADER bmiHeader;
        RGBQUAD bmiColors[256];
    };

    sAPP_Windows_Bitmap tmp_w_bitmap;

    tmp_w_bitmap.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
    tmp_w_bitmap.bmiHeader.biWidth = _width;
    tmp_w_bitmap.bmiHeader.biHeight = -1 * _height;
    tmp_w_bitmap.bmiHeader.biPlanes = 1;
    tmp_w_bitmap.bmiHeader.biBitCount = 8;
    tmp_w_bitmap.bmiHeader.biCompression = BI_RGB;
    tmp_w_bitmap.bmiHeader.biSizeImage = 0;
    tmp_w_bitmap.bmiHeader.biXPelsPerMeter = 0;
    tmp_w_bitmap.bmiHeader.biYPelsPerMeter = 0;
    tmp_w_bitmap.bmiHeader.biClrUsed = 256;
    tmp_w_bitmap.bmiHeader.biClrImportant = 0;

    for (unsigned int i = 0; i < 256; i++)
    {
        tmp_w_bitmap.bmiColors[i].rgbRed = (_table_ptr[i] >> 8) & 0x0ff;
        tmp_w_bitmap.bmiColors[i].rgbGreen = (_table_ptr[i] >> 16) & 0x0ff;
        tmp_w_bitmap.bmiColors[i].rgbBlue = (_table_ptr[i] >> 24) & 0x0ff;
    }

   return CreateDIBitmap(GetDC(APP_hWnd), &tmp_w_bitmap.bmiHeader, CBM_INIT, _index_ptr, (BITMAPINFO*)&tmp_w_bitmap, DIB_RGB_COLORS);
}

Above function is used in the WM_HSCROLL message:

case WM_HSCROLL:
{
                LRESULT slider_pos = SendMessage(GetDlgItem(_hwnd, IDS_DC_SLIDER), TBM_GETPOS, 0, 0);
    
                wchar_t output[4];
                wsprintf(output, L"%ld", slider_pos);
    
                SetWindowText(GetDlgItem(_hwnd, IDS_DC_INTENSITY), output);
    
                int intensity = _wtoi(output);
                int intensity_offset = intensity * 256;
    
                  convert_hbm_texture_256 = APP_Make_HBITMAP_From_Bitmap_Indexed(256, 256, convert_table + intensity_offset, convert_index);
    
                    RedrawWindow(_hwnd, NULL, NULL, RDW_INVALIDATE);
  
}
break; 

in WM_PAINT: message I am displayng the bitmap and Realeasing it

case WM_PAINT:
{
    PAINTSTRUCT ps;
        HDC hdc = BeginPaint(_hwnd, &ps);
        EndPaint(_hwnd, &ps);

    // display 256 preview
        PAINTSTRUCT ps_texture_256;
        HDC hdc_texture_256 = BeginPaint(GetDlgItem(_hwnd, IDS_DC_TEXTURE_256), &ps_texture_256);

            HDC hdc_tmp_256 = CreateCompatibleDC(hdc_texture_256);
            SelectObject(hdc_tmp_256, convert_hbm_texture_256);
            BitBlt(hdc_texture_256, 0, 0, 256, 256, hdc_tmp_256, 0, 0, SRCCOPY);
            DeleteDC(hdc_tmp_256);
            DeleteObject(convert_hbm_texture_256);

        EndPaint(GetDlgItem(_hwnd, IDS_DC_TEXTURE_256), &ps_texture_256);

        return (INT_PTR)TRUE;
}

explanation:

I am using slider to move thru my color tables that has different intensity. Every time I am moving the slider the memory ussage of my application is increasing - I don't know why because I am realeasing DeleteObject(convert_hbm_texture_256); every time after display.

Please note that I am also using that same function APP_Make_HBITMAP_From_Bitmap_Indexed in different part of my application that works fine and dopesn't have that memory issues. But in this case I am only using it once (after drag and drop).

Thanks in advance..



Solution 1:[1]

You definitely have a GDI leak of device contexts in APP_Make_HBITMAP_From_Bitmap_Indexed here:

return CreateDIBitmap(GetDC(APP_hWnd), &tmp_w_bitmap.bmiHeader, CBM_INIT, _index_ptr, (BITMAPINFO*)&tmp_w_bitmap, DIB_RGB_COLORS);

You call GetDC, but never call ReleaseDC. It is a good idea to check entire application with some GDI leaks detection tool like GDIView or Deleaker.


A WM_PAINT handler should deal with the window whose window procedure is called. Such a handler must start with single BeginPaint and end with single EndPaint.

Your handler deals with two windows.


SelectObject returns old object's handle. You must select it back later.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Artem Razin