繁体   English   中英

C++ 代码有一个我无法修复的 memory 泄漏 I

[英]The C++ Code has a memory leak I that i can't fix

我正在尝试创建一个简单的机器人来测试我的技能。 它可以在短时间内正常工作,然后崩溃。 它有一个奇怪的 memory 泄漏,我无法理解。 任何帮助,将不胜感激。

有关代码的额外信息。 它截取屏幕上某些区域的屏幕截图,并比较图像上 4 个像素的 colors,当它看到一个暗像素时,它会自行按下相应的按钮。 是的,我正在尝试使用 c++ 中的钢琴瓷砖机器人 :)

[#include <windows.h>

int R\[4\];

int G\[4\];

int B\[4\];

COLORREF cRef\[4\];


void ScreenShot() {

    HWND DesktopHwnd = GetDesktopWindow();
    RECT DesktopParams;
    HDC DevC = GetDC(DesktopHwnd);
    GetWindowRect(DesktopHwnd, &DesktopParams);
    DWORD Width = DesktopParams.right - DesktopParams.left;
    DWORD Height = DesktopParams.bottom - DesktopParams.top;

    DWORD FileSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + (sizeof(RGBTRIPLE) + 1 * (Width * Height * 4));
    char* BmpFileData = (char*)GlobalAlloc(0x0040, FileSize);
    //std::cout << (BmpFileData);
    PBITMAPFILEHEADER BFileHeader = (PBITMAPFILEHEADER)BmpFileData;
    PBITMAPINFOHEADER BInfoHeader = (PBITMAPINFOHEADER)&BmpFileData\[sizeof(BITMAPFILEHEADER)\];

    BFileHeader->bfType = 'BM'; // BM
    BFileHeader->bfSize = sizeof(BITMAPFILEHEADER);
    BFileHeader->bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);

    BInfoHeader->biSize = sizeof(BITMAPINFOHEADER);
    BInfoHeader->biPlanes = 1;
    BInfoHeader->biBitCount = 24;
    BInfoHeader->biCompression = BI_RGB;
    BInfoHeader->biHeight = Height - 1079;
    BInfoHeader->biWidth = Width - 1522;

    RGBTRIPLE *Image = (RGBTRIPLE*)&BmpFileData\[sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER)\];
    //RGBTRIPLE color;

    HDC CaptureDC = CreateCompatibleDC(DevC);
    HBITMAP CaptureBitmap = CreateCompatibleBitmap(DevC, Width, Height);
    SelectObject(CaptureDC, CaptureBitmap);
    BitBlt(CaptureDC, -753, -566, Width, Height, DevC, 0, 0, SRCCOPY | CAPTUREBLT);
    GetDIBits(CaptureDC, CaptureBitmap, 0, Height, Image, (LPBITMAPINFO)BInfoHeader, DIB_RGB_COLORS);

    for (size_t i = 0; i < 4; i++)
    {
        cRef\[i\] = GetPixel(CaptureDC, (100 * i) + 2, 0);
    }

    for (size_t i = 0; i < 4; i++)
    {
        R\[i\] = GetRValue(cRef\[i\]);
        G\[i\] = GetGValue(cRef\[i\]);
        B\[i\] = GetBValue(cRef\[i\]);
    }


}

int main()
{

    // This structure will be used to create the keyboard
    // input event.
    INPUT ip;

    // Pause for 5 seconds.
    Sleep(3000);

    // Set up a generic keyboard event.
    ip.type = INPUT_KEYBOARD;
    ip.ki.wScan = 0; // hardware scan code for key
    ip.ki.time = 0;
    ip.ki.dwExtraInfo = 0;

    while (true)
    {

        ScreenShot();

        for (size_t i = 0; i < 4; i++)
        {
            if (R\[i\] == 17 && B\[i\] == 17 && G\[i\] == 17)
            {
                if (i == 0)
                {
                    // Press the "A" key
                    ip.ki.wVk = 0x41;  // virtual-key code for the "a" key
                    ip.ki.dwFlags = 0; // 0 for key press
                    SendInput(1, &ip, sizeof(INPUT));

                    // Release the "A" key
                    ip.ki.dwFlags = KEYEVENTF_KEYUP; // KEYEVENTF_KEYUP for key release
                    SendInput(1, &ip, sizeof(INPUT));
                }

                if (i == 1)
                {
                    // Press the "S" key
                    ip.ki.wVk = 0x53;  // virtual-key code for the "S" key
                    ip.ki.dwFlags = 0; // 0 for key press
                    SendInput(1, &ip, sizeof(INPUT));

                    // Release the "S" key
                    ip.ki.dwFlags = KEYEVENTF_KEYUP; // KEYEVENTF_KEYUP for key release
                    SendInput(1, &ip, sizeof(INPUT));
                }
                if (i == 2)
                {
                    // Press the "D" key
                    ip.ki.wVk = 0x44;  // virtual-key code for the "D" key
                    ip.ki.dwFlags = 0; // 0 for key press
                    SendInput(1, &ip, sizeof(INPUT));

                    // Release the "D" key
                    ip.ki.dwFlags = KEYEVENTF_KEYUP; // KEYEVENTF_KEYUP for key release
                    SendInput(1, &ip, sizeof(INPUT));
                }
                if (i == 3)
                {
                    // Press the "D" key
                    ip.ki.wVk = 0x46;  // virtual-key code for the "D" key
                    ip.ki.dwFlags = 0; // 0 for key press
                    SendInput(1, &ip, sizeof(INPUT));

                    // Release the "D" key
                    ip.ki.dwFlags = KEYEVENTF_KEYUP; // KEYEVENTF_KEYUP for key release
                    SendInput(1, &ip, sizeof(INPUT));
                }
            }
            
            Sleep(2);
        }
    }
}]

运行 15.9 秒后,它会泄漏 1.4 GB 的 memory。

您需要将此GlobalAllocGlobalFree匹配。 请参阅https://docs.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-globalalloc

可能只是GlobalFree(BmpFileData); 在 function 的末尾。

您应该调用GlobalFree的另一种方法是将其包装在 RAII 控制类型中: std::unique_ptr 第一部分很简单,这样做:

auto BmpFileData = std::unique_ptr<char>(GlobalAlloc(0x0040, FileSize));

会给你一个指向正确位置的指针,但是当它超出 scope 时,它会调用你不想要的常规delete 幸运的是,您可以忽略破坏:

auto BmpFileData = std::unique_ptr<char>(GlobalAlloc(0x0040, FileSize), GlobalFree);

应该为你工作。

暂无
暂无

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

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