我的hdc / hbitmap的内存泄漏在哪里?

时间:2018-10-29 11:25:09

标签: c++ memory-leaks hbitmap hdc

所以我注意到我的代码的一部分在调用时会泄漏很多内存,我试图找出泄漏的原因或原因,但是我处于死胡同。

我尝试使用Visual Studio 2017调试器进行快照以找出泄漏发生的位置,但是据此,没有任何重大泄漏。我还尝试了一次Deleaker,我曾经工作过一次,它告诉我泄漏了HDC和HBITMAP,但无法告诉我多少内存。

第一个功能是可能泄漏的GetScreenBmp,但是我不能正确释放所有内容吗?我知道我没有删除hBitmap,但是我需要返回它。那是内存泄漏的地方吗?

HBITMAP GetScreenBmp(HDC hdc, int screenPositionX, int screenPositionY, int screenSizeX, int screenSizeY) {
// Get screen dimensions
int nScreenWidth = GetSystemMetrics(SM_CXSCREEN);
int nScreenHeight = GetSystemMetrics(SM_CYSCREEN);
int nMousePositionX = 0, nMousePositionY = 0;

// Create compatible DC, create a compatible bitmap and copy the screen using BitBlt()
HDC hCaptureDC = CreateCompatibleDC(hdc);
HBITMAP hBitmap = CreateCompatibleBitmap(hdc, screenSizeX, screenSizeY);
HGDIOBJ hOld = SelectObject(hCaptureDC, hBitmap);
BOOL bOK = BitBlt(hCaptureDC, 0, 0, screenSizeX, screenSizeY, hdc, screenPositionX, screenPositionY, SRCCOPY | CAPTUREBLT);

SelectObject(hCaptureDC, hOld); // always select the previously selected object once done
DeleteObject(hOld);
DeleteDC(hCaptureDC);

return hBitmap;

第二部分是这段代码,我不确定我是否正确删除了所有内容。

HDC hdc = GetDC(0);
    HBITMAP hBitmap = GetScreenBmp(hdc, currentSplitInformationArray.screenPositionX, currentSplitInformationArray.screenPositionY, currentSplitInformationArray.screenSizeX, currentSplitInformationArray.screenSizeY);
    BITMAPINFO MyBMInfo = { 0 };
    MyBMInfo.bmiHeader.biSize = sizeof(MyBMInfo.bmiHeader);

    // Get the BITMAPINFO structure from the bitmap
    if (0 == GetDIBits(hdc, hBitmap, 0, 0, NULL, &MyBMInfo, DIB_RGB_COLORS)) {
        MessageBox(NULL, "Resource not available\nDo you want to try again?", "Account Details", MB_ICONWARNING | MB_CANCELTRYCONTINUE | MB_DEFBUTTON2);
    }

    // create the bitmap buffer
    BYTE* lpPixels = new BYTE[MyBMInfo.bmiHeader.biSizeImage];

    // Better do this here - the original bitmap might have BI_BITFILEDS, which makes it
    // necessary to read the color table - you might not want this.
    MyBMInfo.bmiHeader.biCompression = BI_RGB;
    MyBMInfo.bmiHeader.biHeight = currentSplitInformationArray.screenSizeY * -1;

    // get the actual bitmap buffer
    if (0 == GetDIBits(hdc, hBitmap, 0, currentSplitInformationArray.screenSizeY, (LPVOID)lpPixels, &MyBMInfo, DIB_RGB_COLORS)) {
        MessageBox(NULL, "Resource not available\nDo you want to try again?", "Account Details", MB_ICONWARNING | MB_CANCELTRYCONTINUE | MB_DEFBUTTON2);
    }

    ::SendMessage(testingComparison, STM_SETIMAGE,
        (WPARAM)IMAGE_BITMAP, (LPARAM)hBitmap);

    DeleteObject(&MyBMInfo);
    DeleteObject(hBitmap);
    ReleaseDC(NULL, hdc);
    delete[] lpPixels;

如果这是以前已经回答过的问题,或者答案很容易被接受,请您提前抱歉,但是我已经尝试了几个小时来解决它。

2 个答案:

答案 0 :(得分:0)

使用工具来跟踪您的泄漏/分配(顺便说一句,您没有首先发现泄漏的位置)。

由于使用的是Visual Studio c ++,因此可以使用内置工具。基本上,将这三行结合起来即可完成工作。

    _CrtSetDbgFlag ( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );//to enable, safe to always set somewhere around program startup - on normal exit this will print whatever you leaked

    //_CrtDumpMemoryLeaks();//Dumps to see what has already been allocated

    //_CrtSetBreakAlloc(#number);//Use this to set breakpoint using the allocation number from heap dump to see where allocation takes place. If allocation happends before this line it will not work.

答案 1 :(得分:0)

好的,我找到了解决方案。 STM_SETIMAGE消息返回前一个图像,您必须自己处理。 https://docs.microsoft.com/en-us/windows/desktop/Controls/stm-setimage

下一次,我可能应该学会更好地阅读文档,对不起,浪费大家的时间。

::SendMessage(testingComparison, STM_SETIMAGE,
            (WPARAM)IMAGE_BITMAP, (LPARAM)hBitmap);

只需完成

即可修复
HBITMAP oldBitmap = (HBITMAP)::SendMessage(testingComparison, STM_SETIMAGE,
        (WPARAM)IMAGE_BITMAP, (LPARAM)hBitmap);
    DeleteObject(oldBitmap);