我的代码在我的计算机和其他测试虚拟机上运行正常,但在客户的计算机上,行为未定义。有时,在_tmain中的MessageBox上按OK后,编译的exe使用100%的CPU,有时它会被炸出。
#include <windows.h>
#include <tchar.h>
#include <strsafe.h>
DWORD GetVS(TCHAR **sGetVS)
{
DWORD dwSize = 1024;
*sGetVS = (TCHAR *) calloc(dwSize,sizeof(TCHAR));
// Buffer for the environment variable value.
TCHAR *sBuffEnv = (TCHAR *) calloc(4096+1,sizeof(TCHAR));
DWORD dwRet = GetEnvironmentVariable(L"VS90COMNTOOLS", sBuffEnv, 4096);
if (dwRet)
{
StringCchCopy(*sGetVS,_tcslen(sBuffEnv)+1,sBuffEnv);
MessageBox(0,sBuffEnv,*sGetVS,0);
_tcslwr_s(*sGetVS,_tcslen(*sGetVS)+1); // +1 is required for the null char
}
free(sBuffEnv);sBuffEnv=NULL;
return 1;
}
int _tmain(int argc, _TCHAR* argv[])
{
TCHAR *sTemp = NULL;
GetVS(&sTemp);
MessageBox(0,sTemp,L"",0);
free(sTemp);
return 0;
}
我已尝试删除上一个free
,甚至在sTemp=NULL;
之后添加了free
,但同样的问题也在发生。
谢谢!
答案 0 :(得分:1)
我看到两个问题,它们都涉及"VS90COMNTOOLS"
的可能值的长度。
第一个GetEnvironmentVariable
使用不当。如果传入的缓冲区不足以容纳环境变量值,则GetEnvironmentVariable
的返回值是保存该值所需的字符数,包括空终止符。如果函数因缓冲区不够大而失败,则返回值不会为代码假定为零。您应该看看返回值是否为0(对于失败,例如未找到)或者是否大于传入的缓冲区的大小(太小)。
其次,dwSize
用于为sGetVS
分配1024个字符,其中缓冲区sBuffEnv
被分配4097个字符。如果sBuffEnv
中返回的值大于1024个字符,则在执行sGetVS
时会溢出为StringCchCopy
分配的缓冲区,这将导致令人讨厌的堆损坏导致您的应用程序中止(或执行任何数量奇怪的事情。)
如果环境变量太大而无法放入提供的缓冲区,则GetEnvironmentVariable
的返回值是缓冲区能够保存变量所需的大小。在这种情况下,sBuffEnv
的内容是未定义的(可能是未触及的,可能是带有或不带有null终止符的截断值,包含垃圾......,不能保证调用后它可能包含的内容)。如果是这种情况,则在执行StringCchCopy
时可能会使用错误数据。