私はガベージ コレクションに関する多くの記事を読みましたが、ほとんどすべての記事がヒープ メモリについて述べています。だから私の質問は「ガベージコレクションはスタックメモリまたはヒープメモリ、またはその両方を収集します」です。
9 に答える
ヒープメモリを収集します。通常、スタック メモリは、実行パスがスコープの最後に到達すると自動的に収集されます。例えば:
void fun()
{
int n; // reservation on the stack as part of the activation record
...
} // returning the stack pointer to where it was before entering the scope
実際、C++ のような言語では、スタックに割り当てられた変数は変数と呼ばれauto
ます。
ヒープメモリ。
ガベージ コレクションは、使用されなくなったメモリの割り当てを解除する方法です。「もう使用されていない」部分が難しい場合があります。スタックを使用すると、関数が戻るとすぐに、ローカル変数がもう使用されていないことを確信できます (プログラマーのエラーを除く)。そのため、ほぼすべての言語/ランタイムでその時点で自動的に割り当てが解除されます。
スタックが「スタック」と呼ばれるのは、まさに「スタック ポリシー」、別名 LIFO (後入れ先出し) で管理されるメモリのゾーンであるためです。スタック上の割り当てが「スタックの方法」で行われなかった場合、それはスタックではなくヒープと呼ばれます。
ガベージ コレクションは、ヒープ上に物を割り当てるという問題に対処するために発明されました。つまり、どの部分が最初に解放されるかを予測できないという問題です。GC は、スタック管理が不十分なメモリ割り当ての問題を対象としています。
スタックは後入れ先出しなので、ガベージ コレクションの必要はありません。
--訂正--当たり前!
私たちの誰も知らないプロファイラーを使用している場合を除き、ヒープが主な懸念事項です。これは、ほとんどの人が、高く評価されているツールからの指示に反応するだけだからです。この投稿を最後まで読んで、静的に割り当てられたメモリ エラーを指摘するほとんどのプロファイリング ツールが通常正しいことを確認してください。プロファイリングは、単純なリークやガベージ コレクションを超えたものにする必要があります。
Cで例を挙げましょう:
#include <stdlib.h>
#include <string.h>
int main(void)
{
char *am_i_leaking;
am_i_leaking = strdup("Now, that's subjective!");
return 0;
}
このプログラムを実行する OS がヒープを自動的に再利用しない場合は、問題が発生しています。実際に使用されていることを行わない最新の OS は考えられません。
これを見てみましょう:
char *foo(void)
{
static char bar[1024];
memset(bar, 0, sizeof(bar));
snprintf(bar, sizeof(bar -1), "Do wa diddy diddy dum diddy do");
return bar;
}
コンパイラがそれをどのように割り当てるかは、コンパイラ次第です。それを使用して結果をいじることができる場合は、コンパイラが壊れている可能性があります。それでも、一度に 100 個のスレッドがその関数に入る場合、コンパイラが魔法のように私が何を意味するのかを理解し、私が心配することなく相互排除または動的割り当てを導入しない限り、結果は確かにゴミです。プロファイリング ヒープに戻ります。
つまり、私たちの生涯において、ガベージ コレクションはヒープに関連しています。将来、スタックに手を加えて物事を「最適化」しようとすることを期待してください。そして、その努力が、多くの CEO が要求する解釈された言語になることを期待してください。
これは、ストレージがたまたま何であれ、メモリエラーを無視することが良いことであるという意味ではありません。
スタックは、メソッドの引数とローカル変数が存在する場所です。メソッドを終了すると、スタック ポインターは自動的にデクリメントされます (特定の実装によってはインクリメントされます)。これは、ほとんどのプログラミング言語に当てはまります。
対照的に、ガベージ コレクションはヒープでのみ機能します。
少なくとも Java では、そのスタック フレームを離れると、スタックは自動的に割り当て解除されるため、ガベージ コレクションを行う必要はありません。
私は Java プログラマーなので、この問題はありませんが、実際に C++ では (聞いたことがあります)、スタックにオブジェクトを割り当てることができ、そのスタック フレームを離れることができるため、これには注意が必要です。オブジェクトの割り当てが解除され、使用できなくなります。
特定のテクノロジーについては言及していませんが、その使用は言語間でかなり一般的です。
ガベージ コレクターはマネージド ヒープでのみ機能します。1 つのプロセスに複数のヒープが存在する場合があり、その一部はガベージ コレクションされません。
スタックに割り当てられた変数は、メソッドが戻るときに割り当てが解除されます。ガベージ コレクターはこれらの変数を使用してライブ参照を見つけますが、メモリは収集しません。