我确信以下有一个合理的解释,但我有点困惑。
问题在于创建_TCHAR[CONSTANT]
,_TCHAR*
的函数,将它们连接起来并返回结果。
出于某种原因,whatTheHeck()
对_tmain()
的调用会返回乱码。
_TCHAR* whatTheHeck(_TCHAR* name) {
_TCHAR Buffer[BUFSIZE];
DWORD dwRet;
dwRet = GetCurrentDirectory(BUFSIZE, Buffer);
_TCHAR* what = new _TCHAR[BUFSIZE];
what = _tcscat(Buffer, TEXT("\\"));
what = _tcscat(what, name);
return what;
}
int _tmain(int argc, _TCHAR* argv[]) {
_TCHAR* failure = whatTheHeck(TEXT("gibberish);")); // not again ..
_tprintf(TEXT("|--> %s\n"), failure);
_TCHAR* success = createFileName(TEXT("readme.txt")); // much better
_tprintf(TEXT("|--> %s\n"), success);
return 0;
}
相比之下,当堆上工作时,按预期工作。
_TCHAR* createFileName(_TCHAR* name) {
_TCHAR* Buffer = new _TCHAR[BUFSIZE];
DWORD dwRet;
dwRet = GetCurrentDirectory(BUFSIZE, Buffer);
Buffer = _tcscat(Buffer, TEXT("\\"));
Buffer = _tcscat(Buffer, name);
return Buffer;
}
为什么会有差异?
是因为_tcscat()
连接内存地址而不是内容并返回清除堆栈吗?
答案 0 :(得分:14)
您的代码存在很多问题。让我们把它拆开,我们是否应该:
_TCHAR* whatTheHeck(_TCHAR* name) // We're inside a local scope
{
_TCHAR Buffer[BUFSIZE]; // "Buffer" has automatic storage
_TCHAR* what = new _TCHAR[BUFSIZE]; // "what" points to newly allocated dyn. memory
what = _tcscat(Buffer, TEXT("\\")); // Oh no, we overwrite "what" - leak!
// Now what == Buffer.
what = _tcscat(what, name); // Equivalent to "_tcscat(Buffer, name)"
return Buffer; // WTPF? We're returning a local automatic!
}
正如你所看到的那样,你们都在使用无偿且鲁莽的new
导致内存泄漏,并且你还在本地对象的生命周期内返回它的地址!
我强烈建议
strcat
并了解“来源”和“目的地”,strcat
,而是使用更安全的版本,例如strncat
,strncat
,而是使用std::string
。答案 1 :(得分:4)
这是因为_tcscat
将连接到目标参数(第一个),然后返回它。因此,它返回一个指向数组Buffer
的指针,并将其存储在此行的what
中:
what = _tcscat(Buffer, TEXT("\\"));
然后返回此指针,一旦您尝试使用它,就会有未定义的行为,因为本地Buffer
不再存在。
此外,上面的行还会导致为what
分配的内存泄露:
_TCHAR* what = new _TCHAR[BUFSIZE];
what = _tcscat(Buffer, TEXT("\\")); // this loses the memory allocated
// in the previous line
答案 2 :(得分:0)
未初始化动态分配的内存what
。它包含胡言乱语。 _tcscat
期望字符串正确地以空值终止。
_TCHAR* what = new _TCHAR[BUFSIZE]();
这会将what
填充为'\0'
个字符。
_TCHAR* what = new _TCHAR[BUFSIZE];
what[0] = '\0';
这正确地终止了空字符串。
GetCurrentDirectory
不期望缓冲区以空值终止。它写了一些东西,并正确地null终止它。然后,您可以将其传递给连接函数。
作为旁注,您的函数似乎容易受到缓冲区溢出的影响。显然你允许GetCurrentDirectory
填写你分配的所有内容,然后你想要附加它而不关心是否还有剩余的空间。
答案 3 :(得分:0)
_TCHAR* what = new _TCHAR[BUFSIZE];
what = _tcscat(Buffer, TEXT("\\"));
你是不是用what
覆盖了Buffer
,它是函数的局部变量。一旦堆栈被展开,Buffer
就会超出范围,从而获得意外的值。这也是内存泄漏。
在堆分配方案中,您可能更愿意将指针声明为const
以避免此类危险:
_TCHAR* const what = new _TCHAR[BUFSIZE];
^^^^^ (avoids overwriting)
更好的方法是使用std::string
并摆脱这些小问题。