简体   繁体   English

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

[英]Where is the memory leak from my hdc/hbitmap?

so I've noticed that part of my code leaks a lot of memory when it's called and I've tried to find out where or why it leaks but I'm at a dead end. 所以我注意到我的代码的一部分在调用时会泄漏大量内存,并且我试图找出泄漏的原因或原因,但是我处于死胡同。

I've tried the Visual Studio 2017 debugger to take snapshots to find out where the leak happens but according to that there aren't any major leaks. 我尝试使用Visual Studio 2017调试器进行快照以找出泄漏发生的位置,但据此没有任何重大泄漏。 I've also tried Deleaker which I got working once which told me I leaked HDC and HBITMAP but couldn't tell me how much memory. 我也尝试过Deleaker,我曾经工作过一次,它告诉我泄漏了HDC和HBITMAP,但无法告诉我多少内存。

The first function is the GetScreenBmp where the leak might be, but aren't I releasing everything properly? 第一个功能是可能泄漏的GetScreenBmp,但是我不能正确释放所有内容吗? I know I'm not deleting hBitmap but I need to return that. 我知道我没有删除hBitmap,但是我需要返回它。 Is that where the memory leak is? 那是内存泄漏的地方吗?

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;

The second part is this piece of code, which I'm not entirely sure if I'm deleting everything properly. 第二部分是这段代码,我不确定是否要正确删除所有内容。

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;

I'm sorry in advance if this is something that has been answered before or if the answer is easily googable, but I've been trying for a few hours to fix it. 如果这是之前已经回答过的问题,或者如果答案很容易接受,我会很抱歉,但是我已经尝试了几个小时来解决它。

Use tools to track your leaks/allocations (btw. you didn't post how you found the leaks in the first place). 使用工具来跟踪您的泄漏/分配(顺便说一句,您最初并没有发布发现泄漏的方式)。

Since you are using visual studio c++ you may use the built-in tools. 由于您使用的是Visual Studio c ++,因此可以使用内置工具。 Basicly a combination of the these 3 lines can get the job done. 基本上,将这3条线组合在一起就可以完成工作。

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

Okay I found the solution. 好吧,我找到了解决方案。 The STM_SETIMAGE message returns the previous image and you have to handle it yourself. STM_SETIMAGE消息返回前一个图像,您必须自己处理。 https://docs.microsoft.com/en-us/windows/desktop/Controls/stm-setimage https://docs.microsoft.com/zh-CN/windows/desktop/Controls/stm-setimage

I should probably learn to better read the documentation next time, sorry for wasting everyone's time with this one. 下次我可能应该学会更好地阅读文档,对于为此浪费大家的时间感到抱歉。

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

Fixed it by simply doing 只需修复即可解决

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM