简体   繁体   中英

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

I am trying to create a simple bot to test my skills on it. It works fine for a short time then it crashes. it has a weird memory leak which I can not understand how. Any help would be appreciated.

Extra info about the code. It takes a screenshot of the certain are on the screen and compares looks the colors of 4 pixels on the image and when it sees a dark pixel it presses the according button itself. Yes I'm trying to my a piano tiles bot in 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);
        }
    }
}]

it leaks 1.4 GB of memory after 15.9 seconds of running.

You need to match this GlobalAlloc with a GlobalFree . See https://docs.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-globalalloc

Possibly just GlobalFree(BmpFileData); at the end of your function.

An alternative to calling GlobalFree which you should be doing, is to wrap it up in a RAII controlled type: std::unique_ptr . The first part is easy, doing this:

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

Will get you a pointer, to the right place, but when it goes out of scope it will call a regular delete which you don't want. Luckily, you can overide the destruction:

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

Should work for you.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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