9

我相信以下有一个合理的解释,但我仍然有点困惑。

问题在于创建 a _TCHAR[CONSTANT]、 a _TCHAR*、连接它们并返回结果的函数。

whatTheHeck()由于某种原因,对from的调用_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()连接内存地址而不是它们的内容并返回清除堆栈吗?

4

4 回答 4

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,并且还返回了一个本地对象在其生命周期之后的地址!

我强烈推荐

  1. 阅读文档strcat并了解“来源”和“目的地”,
  2. 不使用strcat,而是更安全的版本strncat,例如
  3. 不使用strncat,而是std::string
于 2011-07-29T10:51:13.270 回答
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
于 2011-07-29T10:45:25.600 回答
0
_TCHAR* what = new _TCHAR[BUFSIZE];
what = _tcscat(Buffer, TEXT("\\"));

你不是whatBuffer函数的局部变量覆盖吗。一旦堆栈展开,Buffer就会超出范围,因此您会得到意想不到的值。这也是内存泄漏。

在堆分配场景中,您可能更喜欢声明指针 aconst以避免此类危险:

_TCHAR* const what = new _TCHAR[BUFSIZE];
        ^^^^^ (avoids overwriting)

更好的方法是使用std::string并摆脱这些小问题。

于 2011-07-29T10:50:02.480 回答
0

动态分配的内存what指向未初始化。它包含胡言乱语。_tcscat期望字符串正确地以空值结尾。

_TCHAR* what = new _TCHAR[BUFSIZE]();

这充满what'\0'字符。

_TCHAR* what = new _TCHAR[BUFSIZE];
what[0] = '\0';

这会正确终止空字符串。

GetCurrentDirectory不希望缓冲区以空值终止。它向其中写入一些内容并正确地以空值终止它。然后,您可以将其传递给连接函数。


附带说明一下,您的函数似乎容易受到缓冲区溢出的影响。显然你允许GetCurrentDirectory填满你分配的所有东西,然后你想追加它而不关心是否还有剩余空间。

于 2011-07-29T10:42:46.437 回答