简体   繁体   中英

how can I allocate an array on the stack if the size is not known at compile time?

I'm writing a c++ program with visual studio and I have written this code

DWORD GetProcIDByName(const char* procName) {
    HANDLE hSnap;
    BOOL done;
    PROCESSENTRY32 procEntry;

    ZeroMemory(&procEntry, sizeof(PROCESSENTRY32));
    procEntry.dwSize = sizeof(PROCESSENTRY32);

    hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
    done = Process32First(hSnap, &procEntry);
    do {
        /* here */ char file_str[sizeof(procEntry.szExeFile)];
        int wc_convert = WideCharToMultiByte(CP_ACP, 0, procEntry.szExeFile, sizeof(procEntry.szExeFile), file_str, sizeof(file_str), NULL, NULL);
        if (_strnicmp(file_str, procName, sizeof(file_str)) == 0) {
            return procEntry.th32ProcessID;
        }
    } while (Process32Next(hSnap, &procEntry));

    return 0;
}

in order to convert the value procEntry.szExeFile from a WCHAR* (wide unicode character array), to a standard char* to compare, I had to make a char* buffer for it. I wrote the line

char file_str[sizeof(procEntry.szExeFile)]; 

and realized later that I should use heap memory for this buffer that will change sizes depending on the process name, but I was surprised to see that my visual studio had no problem with this code and I was able to build it with no compiler errors. I haven't run it yet and I probably will not because I imagine if this runs there is a potential for buffer overflow and undefined behaviour

I don't have any issue, but I am curious about why I was able to write this code without getting a compiler error. If the process name is not known at compile time, how can I allocate this buffer on the stack?

The szExeFile field is not dynamic length. It is a fixed-length array of MAX_PATH characters, holding a null-terminated string.

Note that:

  • sizeof() reports a size in bytes
  • szExeFile is an array of wchar_t characters, in your case
  • wchar_t is 2 bytes in size on Windows.

So, when you declare your char[] array as char file_str[sizeof(procEntry.szExeFile)]; , it will have a static compile-time size of MAX_PATH*2 char s. Which should be large enough to easily handle most conversions from wchar_t[] to char[] in this case.

BTW, your use of sizeof(procEntry.szExeFile) in the 4th parameter of WideCharToMultiByte() is wrong. That parameter expects a character count, not a byte count. Use lstrlenW(procEntry.szExeFile) or wcslen(procEntry.szExeFile) instead. Or just -1 to let WideCharToMultiByte() count the wide characters for you.

That being said, an easier solution is to use Process32FirstA() / Process32NextA() instead. Or, change your function to take a Unicode wchar_t string as input. Either way, then you won't have to convert the procEntry.szExeFile at all, just use it as-is.

Also, you are leaking the HANDLE from CreateToolhelp32Snapshot() , you need to call CloseHandle() when you are done using it.

Try this:

DWORD GetProcIDByName(const char* procName) {
    DWORD dwProcessID = 0;

    PROCESSENTRY32A procEntry = {};
    procEntry.dwSize = sizeof(procEntry);
   
    HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
    if (hSnap != INVALID_HANDLE_VALUE) {
        BOOL ok = Process32FirstA(hSnap, &procEntry);
        while (ok) {
            if (_stricmp(procEntry.szExeFile, procName) == 0) {
                dwProcessID = procEntry.th32ProcessID;
                break;
            }
            ok = Process32NextA(hSnap, &procEntry);
        }
        CloseHandle(hSnap);
    }

    return dwProcessID;
}

Or this:

DWORD GetProcIDByName(const wchar_t* procName) {
    DWORD dwProcessID = 0;

    PROCESSENTRY32W procEntry = {};
    procEntry.dwSize = sizeof(procEntry);
   
    HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
    if (hSnap != INVALID_HANDLE_VALUE) {
        BOOL ok = Process32FirstW(hSnap, &procEntry);
        while (ok) {
            if (_wcsicmp(procEntry.szExeFile, procName) == 0) {
                dwProcessID = procEntry.th32ProcessID;
                break;
            }
            ok = Process32NextW(hSnap, &procEntry);
        }
        CloseHandle(hSnap);
    }

    return dwProcessID;
}

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