无法释放HBITMAP,使用CreateDIBitmap存在内存泄漏

发布于 2025-01-15 19:55:36 字数 3142 浏览 4 评论 0原文

我正在使用 CreateDIBitmap() 并始终通过 DeleteObject() 释放它。 当我的滑块移动时我使用它,我注意到使用的内存每次都在增加。

这是我从索引位图数据创建 HBITMAP 的函数:

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);
}

上面的函数用在 WM_HSCROLL 消息中:

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; 

在 WM_PAINT: 消息中,我正在显示位图并释放它

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;
}

说明:

我正在使用滑块在具有不同强度的颜色表中移动。 每次我移动滑块时,应用程序的内存使用量都会增加 - 我不知道为什么,因为我正在释放DeleteObject(convert_hbm_texture_256);每次显示后。

请注意,我也使用相同的函数 APP_Make_HBITMAP_From_Bitmap_Indexed 在我的应用程序的不同部分,工作正常并且没有内存问题。 但在这种情况下,我只使用它一次(拖放后)。

提前致谢..

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

稚气少女 2025-01-22 19:55:36

您在 APP_Make_HBITMAP_From_Bitmap_Indexed 中肯定存在设备上下文的 GDI 泄漏:

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

您调用 GetDC,但从未调用 ReleaseDC。最好使用一些 GDI 泄漏检测工具(例如 GDIViewDeleaker


WM_PAINT 处理程序应该处理调用其窗口过程的窗口。这样的处理程序必须以单个 BeginPaint 开始并以单个 EndPaint 结束。

您的处理程序处理两个窗口。


SelectObject 返回旧对象的句柄。您必须稍后再选择它。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文