9

以下は合理的な説明があると確信していますが、それでも私は少し困惑しています。

問題は、、、を作成し_TCHAR[CONSTANT]_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()内容ではなくメモリアドレスを連結し、returnがスタックをパージするためですか?

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

動的に割り当てられたメモリwhatポイントは初期化されません。ジブリッシュが含まれています。_tcscat文字列が適切にnullで終了することを期待します。

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

whatこれは文字でいっぱい'\0'です。

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

これにより、空の文字列が適切に終了します。

GetCurrentDirectoryバッファがnullで終了することを期待していません。それに何かを書き込み、適切にnullで終了します。次に、それを連結関数に渡すことができます。


ちなみに、関数はバッファオーバーフローに対して脆弱であるようです。どうやらあなたはGetCurrentDirectoryあなたが割り当てたすべてを埋めることを許可し、それからあなたはそれ以上のスペースが残っているかどうか気にせずにそれに追加したいと思います。

于 2011-07-29T10:42:46.437 に答える
0
_TCHAR* what = new _TCHAR[BUFSIZE];
what = _tcscat(Buffer, TEXT("\\"));

関数のローカル変数であるを上書きwhatしませんか。Bufferスタックが巻き戻さBufferれると、スコープ外になり、予期しない値が返されます。また、メモリリークです。

constヒープ割り当てのシナリオでは、このような危険を回避するために、ポインターaを宣言することをお勧めします。

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

より良いアプローチはstd::string、そのような小さな問題を使用して回避することです。

于 2011-07-29T10:50:02.480 に答える