Home > Net >  The C Code has a memory leak that I can't fix
The C Code has a memory leak that I can't fix

Time:01-25

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 a certain area on the screen and compares the colors of 4 pixels on the image, and when it sees a dark pixel, it presses the appropriate button itself. Yes, I'm trying to do 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.

CodePudding user response:

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 override the destruction:

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

Should work for you.

CodePudding user response:

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.

  •  Tags:  
  • Related