[英]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 szExeFile
是wchar_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.