0

私はプログラムを書いていて、次の関数がガベージ値を返すために使用するこの問題に直面していました。

int* foo(int temp){
   int x = temp;
   return &x;
}

これに変更すると、正常に機能しました。

int* foo(int *temp){
    int *x = temp;
    return x
}

最初のバージョンの何が問題でしたか?

4

2 に答える 2

7

x最初のバージョンは、ストレージが関数に制限されているローカル変数への参照を返しますfoo。関数が終了すると、xは使用できなくなります。それへの参照を返すことは、ダングリングポインタの1つのインスタンスです。

2番目のバージョンでは、実際には同じポインタ値を渡して返すだけです。これは、関数の存続期間によって制限されないメモリを参照します。したがって、関数が終了した後でも、返されたアドレスは引き続き有効です。

別の選択肢:

int *foo(int temp)
{
    int *x = malloc(sizeof(int));
    *x = temp;
    return x;
}
于 2012-08-20T17:54:04.900 に答える
0

関数ごとにアクティベーションレコードがあり、その関数の実行が開始されるとスタックに作成されます。アクティベーションレコードには、すべてのローカル変数も保持されます。そして、このアクティベーションレコードは、関数の実行が終了すると解放されます。

したがって、ローカル変数のアドレスを返すと、前の関数のアクティブ化レコードのメモリが解放されます。その記憶を間接参照することは、未定義の動作です。

以下の場合、関数は、のローカル変数のアドレスを保持することを意味するをfoo返します。これは有効です。しかし、関数が無効な(のアドレス)を再実行しようとした場合。&xpfuncxfuncpx

int* func
{
   int x;
   int *p;
   ...
   p = foo(&x);
   //using p is valid here
   ...
   return p; //This is invalid
}

int* foo(int *temp)
{
   int *x = temp;
   return x //This is valid
}

以下の場合、funcitonfooはそのローカル変数のアドレスxを関数に返していますfunc。したがって、のローカル変数のpアドレスを保持します。fooしたがって、関数の実行が完了し、そのアクティブ化レコードが解放されるpため、延期は無効になります。foo

int* func
{
   int x;
   int *p;
   ...
   p = foo(x);
   //using p is invalid here
   ...
   return p; //This is invalid
}

int* foo(int temp)
{
   int x = temp;
   return &x; //This is also invalid
}
于 2012-08-21T02:44:57.720 に答える