将堆栈字符串与堆字符串连接会产生奇怪的结果

Sau*_*aul 9 c++ windows string memory-management tchar

我确信以下有一个合理的解释,但我有点困惑.

问题在于创建a _TCHAR[CONSTANT],a _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;
}
Run Code Online (Sandbox Code Playgroud)

相反,当与堆一起工作时,按预期工作.

_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;
}
Run Code Online (Sandbox Code Playgroud)

为什么不同?

是因为_tcscat()连接内存地址而不是内容并返回清除堆栈?

Ker*_* SB 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!
 }
Run Code Online (Sandbox Code Playgroud)

正如您所看到的那样,您既可以使用无偿且鲁莽的方式导致内存泄漏new,并且您还会在其生命周期内返回本地对象的地址!

我强烈建议

  1. 阅读文档strcat并了解"源"和"目的地",
  2. 不使用strcat,但更安全的版本,如strncat,
  3. 不使用strncat,而是使用std::string.