简体   繁体   English

如果在编译时大小未知,如何在堆栈上分配数组?

[英]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我正在用 Visual Studio 编写 c++ 程序,并且我已经编写了这段代码

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.为了将值 procEntry.szExeFile 从 WCHAR*(宽 unicode 字符数组)转换为标准 char* 进行比较,我必须为它创建一个 char* 缓冲区。 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.后来意识到我应该为这个缓冲区使用堆 memory,它会根据进程名称改变大小,但我惊讶地发现我的 Visual Studio 对这段代码没有任何问题,而且我能够在没有编译器错误的情况下构建它。 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. szExeFile字段不是动态长度。 It is a fixed-length array of MAX_PATH characters, holding a null-terminated string.它是一个固定长度的MAX_PATH字符数组,包含一个以 null 结尾的字符串。

Note that:注意:

  • sizeof() reports a size in bytes sizeof()以字节为单位报告大小
  • szExeFile is an array of wchar_t characters, in your case szExeFilewchar_t字符数组,在您的情况下
  • wchar_t is 2 bytes in size on Windows. wchar_t在 Windows 上的大小为 2 个字节。

So, when you declare your char[] array as char file_str[sizeof(procEntry.szExeFile)];因此,当您将char[]数组声明为char file_str[sizeof(procEntry.szExeFile)]; , it will have a static compile-time size of MAX_PATH*2 char s. ,它将具有MAX_PATH*2 char s 的 static 编译时大小。 Which should be large enough to easily handle most conversions from wchar_t[] to char[] in this case.在这种情况下,它应该足够大以轻松处理从wchar_t[]char[]的大多数转换。

BTW, your use of sizeof(procEntry.szExeFile) in the 4th parameter of WideCharToMultiByte() is wrong.顺便说一句,您在WideCharToMultiByte()的第四个参数中使用sizeof(procEntry.szExeFile) ) 是错误的。 That parameter expects a character count, not a byte count.该参数需要字符数,而不是字节数。 Use lstrlenW(procEntry.szExeFile) or wcslen(procEntry.szExeFile) instead.请改用lstrlenW(procEntry.szExeFile)wcslen(procEntry.szExeFile) Or just -1 to let WideCharToMultiByte() count the wide characters for you.或者只是 -1 让WideCharToMultiByte()为您计算宽字符。

That being said, an easier solution is to use Process32FirstA() / Process32NextA() instead.话虽如此,更简单的解决方案是改用Process32FirstA() / Process32NextA() Or, change your function to take a Unicode wchar_t string as input.或者,更改您的 function 以将 Unicode wchar_t字符串作为输入。 Either way, then you won't have to convert the procEntry.szExeFile at all, just use it as-is.无论哪种方式,您都不必转换procEntry.szExeFile ,只需按原样使用即可。

Also, you are leaking the HANDLE from CreateToolhelp32Snapshot() , you need to call CloseHandle() when you are done using it.此外,您正在从CreateToolhelp32Snapshot()泄漏HANDLE ,您需要在完成使用后调用CloseHandle()

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;
}

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

相关问题 我可以在编译时不知道大小的情况下在堆栈上分配`std :: array`吗? - Can I allocate `std::array` on stack without knowing size at compile time? 如果在编译时知道大小,是否有一种干净的方法可以在堆栈上分配可变大小的对象? - Is there a clean way to allocate a variable size object on the stack, if the size is known at compile time? 如何声明一个在编译时不知道大小的数组? - How to declare an array without size known at compile-time? 如果在编译时知道边缘条件,我怎么能忽略一个调用呢? - How can I elide a call if an edge condition is known at compile time? gcc如何分配静态运行时间已知的数组长度 - How does gcc allocate statically run time known length of array 常量大小的数组,在编译时已知..但仅在派生类中 - Array of constant size, known at compile time.. but in the derived classes only 如何使 object 获取并存储任意但编译时已知大小的数组? - How to make an object take and store an Array of arbitrary, but compile-time known size? 为什么在堆栈上分配任意大小的数组是不可能的? - Why is it impossible to allocate an array of an arbitrary size on the stack? 如果在编译时未知其大小,是否可以在堆栈上创建一个数组? - Is it possible to create an array on the stack, if its size is unknown at compile time? memcpy在编译时已知大小 - memcpy where size is known at compile time
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM