函数参数返回值中的calloc

时间:2011-06-02 16:39:52

标签: calloc

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

谢谢!

1 个答案:

答案 0 :(得分:1)

我看到两个问题,它们都涉及"VS90COMNTOOLS"的可能值的长度。

第一个GetEnvironmentVariable使用不当。如果传入的缓冲区不足以容纳环境变量值,则GetEnvironmentVariable的返回值是保存该值所需的字符数,包括空终止符。如果函数因缓冲区不够大而失败,则返回值不会为代码假定为零。您应该看看返回值是否为0(对于失败,例如未找到)或者是否大于传入的缓冲区的大小(太小)。

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

更新

如果环境变量太大而无法放入提供的缓冲区,则GetEnvironmentVariable的返回值是缓冲区能够保存变量所需的大小。在这种情况下,sBuffEnv的内容是未定义的(可能是未触及的,可能是带有或不带有null终止符的截断值,包含垃圾......,不能保证调用后它可能包含的内容)。如果是这种情况,则在执行StringCchCopy时可能会使用错误数据。