1
#include <iostream>
#include <string.h>
using namespace std;

void newBuffer(char* outBuffer, size_t sz) {
    outBuffer = new char[sz];
}

int main(void) {

    const char* abcd = "ABCD";
    char* foo;
    foo = NULL;
    size_t len = strlen(abcd);
    cout<<"Checkpoint 1"<<endl;
    newBuffer(foo, len);
    cout<<"Checkpoint 2"<<endl;

    cout<<"Checkpoint 2-A"<<endl;
    memset(foo, '-', len);
    cout<<"Checkpoint 3"<<endl;
    strncpy(foo, abcd, len);
    cout<<"Checkpoint 4"<<endl;
    cout << foo << endl;

    int hold;
    cin>>hold;
    return 0;

}

このプログラムは、チェックポイント 2-1 と 3 の間でクラッシュします。実行しようとしているのは、char 配列 foo を char '-' に設定することですが、いくつかのアクセスの問題のために失敗します。なぜこれが起こるのかわかりません。事前にどうもありがとうございました!

4

3 に答える 3

6

関数newBuffer内で行われた変更が呼び出し元に表示されるように、関数は参照によって最初のパラメーターを受け入れる必要があります。

void newBuffer(char*& outBuffer, size_t sz) {
    outBuffer = new char[sz];
}

現在のように、呼び出し元の変数のコピーにすぎないnew char[sz]ローカル変数に結果を割り当てるため、関数が返されたときは、何も起こらなかったかのようになります (メモリ リークを除いて)。outBufferfoo

また、バッファを長さABCD4 のサイズに割り当てているという問題があります。つまり、最後に NUL ターミネータ用に予約されているため、そのバッファに最大 3 文字を保持できます。+ 1どこかで長さを追加する必要があります( newBufferC 文字列に特化してはならないため、内部ではなく、関数の呼び出しで行います)。strncpyソース文字列が十分に短い場合にのみバッファを NUL で終了するため、この場合、割り当てたバッファの後にたまたま0メモリ内に が存在するのは幸運です。

delete[] fooまた、作業が終わったらinすることも忘れないでくださいmain(ただし、このサイズのプログラムでは問題になりません)。

于 2012-05-13T16:32:57.683 に答える
2

newBuffer関数が実際には機能しないため、失敗します。これを修正する最も簡単な方法は、宣言を に変更することvoid newBuffer (char *&outBuffer, size_t sz)です。foo書かれているように、新しく割り当てられたメモリのアドレスは、ポインタが値によって渡されるため、実際にはメインのメモリに格納されません。

于 2012-05-13T16:35:17.227 に答える
0

ポインタを値で渡します。ポインタへの参照またはポインタのアドレスのいずれかを渡す必要があります。

そうは言っても、私の見解では、戻り値を使用する方が良いでしょう。

char* newBuffer(size_t sz) {
    return new char[sz];
}

このように記述した場合、このnewBuffer関数は実際には価値がないように見えます。あなたはそれを必要としません。new直接使用することができ、それはより明確になります。

もちろん、C ++を使用している場合、これはすべてかなり無意味です。スマートポインタなどを使用する必要があります。直接string呼び出す必要はありません。newこの質問で話しているバグを修正すると、文字列がnullで終了しておらず、nullターミネータにスペースを割り当てるのを忘れたため、バッファが短すぎて文字列を保持できないという問題が発生します。C ++の優れた点の1つは、Cでの文字列処理の恐怖から逃れることができることです。

于 2012-05-13T16:36:11.087 に答える