簡體   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