4

static関数が戻ると、その中で宣言されているすべてのローカル変数(キーワードを持つものを除く)はガベージコレクションされると思いました。しかし、次のコードを試していると、関数が戻った後も値が出力されます。誰かが理由を説明できますか?

int *fun();
main() {
  int *p;
  p = fun();
  printf("%d",*p); //shouldn't print 5, for the variable no longer exists at this address
}
int *fun() {
  int q;
  q = 5;
  return(&q);
}
4

5 に答える 5

7

Cにはガベージコレクションはありません。変数のスコープが存在しなくなると、何らかの方法でそのスコープにアクセスすることは違法になります。表示されるのはUB(未定義動作)です。

于 2012-10-15T18:05:06.433 に答える
6

これは未定義の動作であり、機能しているように見えることを含め、何でも起こり得ます。メモリはおそらくまだ上書きされていませんが、それはあなたがそれにアクセスする権利を持っているという意味ではありません。しかし、あなたはそうしました!私はあなたの幸せを願います!:)

于 2012-10-15T18:04:51.240 に答える
4

本当に値を失いたい場合は、場所にアクセスしてprintfを実行する前に、少なくとも数行のコードを含む別の関数を呼び出してください。おそらくあなたの価値はそれまでに上書きされるでしょう。

しかし、すでに述べたように、これは未定義の動作です。いつ(またはまったく)クラッシュまたは変更されるかを予測することはできません。しかし、「変更または同じまま」に依存して、これらの仮定のいずれかを使用してアプリケーションをコーディングすることはできません。

私が説明しようとしているのは、前の関数呼び出しから戻った後に別の関数呼び出しを行うと、別のアクティブ化レコードがスタックにプッシュされることです。おそらく、ポインターを介して値にアクセスしていた変数を含む前のレコードを上書きします。

関数とそのデータがスコープ外になると、実際にガベージコレクションを行ったり、saymemset0を実行したりするボディはありません。

于 2012-10-15T18:08:03.340 に答える
2

Cは、Javaでサポートされているガベージコレクションをサポートしていません。ガベージコレクションについて詳しくは、こちらをご覧ください

于 2012-10-15T18:10:03.513 に答える
1

論理的には、q終了すると存在しなくなりfunます。

物理的に(「物理的」の適切に緩い定義の場合)、ストーリーはもう少し複雑で、基盤となるプラットフォームによって異なります。Cはガベージコレクションを行いません(この場合、ガベージコレクションは適用されません)。占有されていたメモリセル(仮想または物理)qはまだ存在し、最後に書き込まれた値が含まれています。アーキテクチャ/オペレーティングシステムなどによっては、プログラムからそのセルにアクセスできる場合がありますが、それは保証されていません。

6.2.4オブジェクトの保存期間

2オブジェクトの存続期間は、ストレージがそのオブジェクト用に予約されることが保証されているプログラム実行の部分です。オブジェクトが存在し、定数アドレス33) を持ち、その存続期間を通じて最後に保存された値を保持します。34) オブジェクトがその存続期間外に参照された場合、動作は定義されていません。ポインタが指す(またはちょうど過ぎた)オブジェクトがその存続期間の終わりに達すると、ポインタの値は不確定になります。
33)「定数アドレス」という用語は、おそらく異なる時間に構築されたオブジェクトへの2つのポインターが等しく比較されることを意味します。同じプログラムを2回実行すると、アドレスが異なる場合があります。

34)揮発性オブジェクトの場合、最後のストアはプログラムで明示的である必要はありません。

「未定義動作」は、問題に対処しないことによって問題に対処するC言語の方法です。基本的に、実装は、問題を完全に無視し、基盤となるOSにいたずらなことをするためにプログラムを強制終了させるまで、選択した方法で状況を自由に処理できます。

あなたの特定のケースでは、終了後にそのメモリセルにアクセスしてfunも何も壊れず、まだ上書きされていませんでした。その動作は、再現可能であることが保証されていません。

于 2012-10-15T18:50:19.313 に答える