私はプログラムを書いていて、次の関数がガベージ値を返すために使用するこの問題に直面していました。
int* foo(int temp){
int x = temp;
return &x;
}
これに変更すると、正常に機能しました。
int* foo(int *temp){
int *x = temp;
return x
}
最初のバージョンの何が問題でしたか?
x
最初のバージョンは、ストレージが関数に制限されているローカル変数への参照を返しますfoo
。関数が終了すると、x
は使用できなくなります。それへの参照を返すことは、ダングリングポインタの1つのインスタンスです。
2番目のバージョンでは、実際には同じポインタ値を渡して返すだけです。これは、関数の存続期間によって制限されないメモリを参照します。したがって、関数が終了した後でも、返されたアドレスは引き続き有効です。
別の選択肢:
int *foo(int temp)
{
int *x = malloc(sizeof(int));
*x = temp;
return x;
}
関数ごとにアクティベーションレコードがあり、その関数の実行が開始されるとスタックに作成されます。アクティベーションレコードには、すべてのローカル変数も保持されます。そして、このアクティベーションレコードは、関数の実行が終了すると解放されます。
したがって、ローカル変数のアドレスを返すと、前の関数のアクティブ化レコードのメモリが解放されます。その記憶を間接参照することは、未定義の動作です。
以下の場合、関数は、のローカル変数のアドレスを保持することを意味するをfoo
返します。これは有効です。しかし、関数が無効な(のアドレス)を再実行しようとした場合。&x
p
func
x
func
p
x
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
}