0

我的代码在我的计算机和我拥有的其他测试虚拟机上运行良好,但在我客户的计算机上,行为未定义。有时,在 _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;after free,但同样的问题正在发生。

谢谢!

4

1 回答 1

1

我看到了两个问题,它们都处理"VS90COMNTOOLS".

首先GetEnvironmentVariable是使用不当。如果传入的缓冲区不足以容纳环境变量值,则返回值GetEnvironmentVariable是容纳该值所需的字符数,包括空终止符。如果函数因缓冲区不够大而失败,则返回值不为零,如您的代码所假设的那样。您应该查看返回值是否为 0(表示失败,例如未找到)或者它是否大于传入的缓冲区大小(太小)。

其次,dwSize用于分配 1024 个字符sGetVS的缓冲区,其中sBuffEnv分配了 4097 个字符。如果返回的值sBuffEnv大于 1024 个字符,您将sGetVS在执行此操作时溢出分配的缓冲区,StringCchCopy这将导致令人讨厌的堆损坏,从而导致您的应用程序中止(或执行任何数量的奇怪事情)。

更新

如果环境变量太大而无法放入提供的缓冲区,则返回值GetEnvironmentVariable是缓冲区能够容纳变量所需的大小。在这种情况下, 的内容sBuffEnv是未定义的(可以保持不变,可以是带或不带空终止符的截断值,包含垃圾......,不能保证在调用后它可能包含什么)。如果是这种情况,您在执行StringCchCopy.

于 2011-06-02T18:36:17.457 回答