-2

次の C++ コード フラグメントを検討してください。関数へのパラメーターとして char * への参照を渡しています。

void name(char **str){
    *str=(char *)"JUSTFORFUN";
}


int main(int argc, const char * argv[])
{
    char *test;
    name(&test);
    cout<<test; //Prints "JUSTFORFUN"
    //delete(test); //Throws error "pointer being freed was not allocated"
    return 0;
}

function name() に「JUSTFORFUN」を格納するために割り当てられたメモリは、スタックに割り当てられていると思います。そのため、制御が name() の外に出ると、(char *)"JUSTFORFUN" に関連付けられたメモリはコンパイラによって解放されているはずです。私の質問は、テストを印刷しても正しい出力が得られるのはなぜですか? ジャンク値を印刷するべきではありませんでしたか?

int に似たようなことをすると。期待どおりの結果が得られます。

void nameint(int **value){
    int val=5;
    *value=&val;
}

int main(int argc, const char * argv[])
{
    int *val;
    nameint(&val);
    cout<<*val; //Prints a junk value 1073828160    
    return 0;
}

int と char * の動作に違いがあるのはなぜですか?

4

4 に答える 4

1

文字列リテラル"JUSTFORFUN"はスタックに保存されません。静的な保存期間があります。function の内部にしか現れないにもかかわらずname、文字列リテラル自体はその関数に対してローカルではありません(文字列リテラルはありません -- それらはすべて静的な保存期間を持ちます)。

そのため、最初のプログラムの動作は実際には明確に定義されています。nameリターンの後val、静的な保存期間を持つ文字列リテラルのアドレスが含まれます。これを印刷します。

2 番目のプログラムでは、関数に対してローカルな int のアドレスを返しています。関数が戻った後、それintはもはや存在しないため、それを使用すると未定義の動作が発生します-典型的なケースでは、現在そのアドレスにあるビットがどのような値になるかをおそらく出力しますが、それが何をするかについての保証はありません.

于 2013-06-23T05:49:10.813 に答える
1

「JUSTFORFUN」はスタックに割り当てられません。これは、プログラムの残りの静的データと共に保存されます。このname関数は、スタックにポインターを格納します。そのポインタは静的データを指しています。

ただし、intスタックに格納されます。関数nameintは、スタック上のその位置へのポインターを返します。そのようなことをすると、プログラムがすぐにクラッシュする可能性があります。

于 2013-06-23T05:49:41.433 に答える
0

2 つの異なるケース:

文字列の場合、生の文字列const char* x = "sdfsdf"は実行可能ファイルの .data セクションに保存されるため、メモリを割り当てませんでした。そのため、プログラムで読み込まれる静的な不変データと考えることができます (メモリ割り当てはまったく割り当てられません)。 !)

2 番目のケースvalでは、関数スタックに割り当てられ、関数が戻ると無効になります。

于 2013-06-23T05:50:00.563 に答える
0

function name() に「JUSTFORFUN」を格納するために割り当てられたメモリは、スタックに割り当てられていると思います

いいえ、そうではありません。文字列リテラルには暗黙的にstatic保存期間があります。それらの寿命はプログラムの寿命です。がなければ、delete最初のプログラムは正しいです。

「解放されたポインターが割り当てられていません」というエラーをスローします

を使用してそのオブジェクトを作成しなかったため、もちろんそうですnew

intとの動作に違いがあるのはなぜchar *ですか?

それが言語の定義方法だからです。2番目のプログラムでは、int 自動保存期間があります(あなたの言葉で「スタックが割り当てられます」)ので、それを囲むスコープ(ここでは関数)の外でそのアドレスを使用すると、未定義の動作が呼び出されます。

于 2013-06-23T05:50:46.340 に答える