我正在尝试编写一个函数,在多个消息框中显示系统中所有线程的拥有进程的PID。
void CheckProcess()
{
LPCSTR blahzix;
HANDLE tsnap = CreateToolhelp32Snapshot (TH32CS_SNAPTHREAD, 0);
THREADENTRY32 tentry;
tentry.dwSize = sizeof (tentry);
BOOL CRec = Thread32First(tsnap, &tentry);
GetLastError();
while (CRec)
{
blahzix = tentry.th32OwnerProcessID;
MessageBox (NULL, NULL, blahzix, MB_OK);
CRec = Thread32Next(tsnap, &tentry);
}
CloseHandle(tsnap);
}
我很困惑为什么这一段时间不起作用所以我在OllyDBG中打开它,发现MessageBox
的代码是第三个参数直接接收PID数据而不是接收地址它将PID存储为字符串,当MessageBox
函数尝试访问存储在00000004的数据时导致访问冲突。如果我删除行blahzix = tentry.th32OwnerProcessID;
并将第三行附加到如下所示: LPCSTR blahzix = "anything";
然后正确显示一个标题为“任何内容”的消息框,而不是崩溃MessageBox
。
为什么会这样?我是否正确认为编译器决定“变量blahzix除了在这个消息框函数中以外没有使用过,它总是等于tentry.th32OwnerProcessID所以它们也可能是同一个变量,我只是摆脱它并制作消息框改为使用那个变量。“
编辑:让我重新解释一下我的问题。如果LPCSTR blahzix = "fdisaf";
使用=运算符并且=运算符应该将左侧变量的值更改为右侧的数据或变量的值,那么为blahzix创建字符串的用法是有效?由于blahzix显然实际上是a pointer,我认为=运算符应该只改变变量指向的位置而不是改变其中的内容。为什么在这个实例中使用=运算符会更改它指向的字符串的数据并在此实例中使用它:blahzix = tentry.th32OwnerProcessID;
更改指针的数据而不是字符串的数据? =运算符不应该改变一个或另一个吗?如何让=运算符指定我想要更改哪些数据?
答案 0 :(得分:4)
THREADENTRY32::th32OwnerProcessID
是DWORD
,不是字符串。将它分配给指针并将其视为字符串是没有意义的。它也是无效的(没有显式强制转换的约束违规);我很惊讶这甚至编译的方式/原因。
不要在编译器上归咎于你自己的错误。编译器错误是非常非常罕见的。
答案 1 :(得分:2)
blahzix = tentry.th32OwnerProcessID;
不会将整数进程ID转换为字符串。它只是将进程id写为blahzix
指向的地址。您没有在此地址拥有内存,因此尝试从中显示字符串会导致未定义的行为。可能会崩溃。
要通过MessageBox
将进程ID显示为字符串,您需要将其转换为char
数组。给定C ++ 11支持,您可以通过更改
blahzix = tentry.th32OwnerProcessID;
MessageBox (NULL, NULL, blahzix, MB_OK);
到
std::string s = std::to_string(tentry.th32OwnerProcessID);
char const *pchar = s.c_str();
MessageBox (NULL, NULL, pchar, MB_OK);
或者,如果您仅限于使用C(问题标记为C ++但代码全部为C),则可以使用
char str[12];
sprintf(str, "%d", tentry.th32OwnerProcessID);
MessageBox (NULL, NULL, str, MB_OK);