gcモジュールを使用する前に、Pythonはどのように循環メモリ参照を検出して解放しますか?
そうではありません。gc は、循環参照を検出して解放するためだけに存在します。非循環参照は、refcounting によって処理されます。
ここで、特定のオブジェクトが参照するオブジェクトのセットを gc がどのようgc_get_references
に決定するかを確認するには、 の関数を見てくださいModules/gcmodule.c
。関連するビットは次のとおりです。
// Where `obj` is the object who's references we want to find
traverseproc traverse;
if (! PyObject_IS_GC(obj))
continue;
traverse = Py_TYPE(obj)->tp_traverse;
if (! traverse)
continue;
if (traverse(obj, (visitproc)referentsvisit, result)) {
Py_DECREF(result);
return NULL;
}
ここでの主な機能はtp_traverse
. 各 C レベルの型はtp_traverse
関数を定義します (または、 のように参照を保持しないオブジェクトの場合は、str
それを に設定しますNULL
)。の 1 つの例tp_traverse
はlist_traverse
、次のトラバーサル関数ですlist
。
static int
list_traverse(PyListObject *o, visitproc visit, void *arg)
{
Py_ssize_t i;
for (i = Py_SIZE(o); --i >= 0; )
Py_VISIT(o->ob_item[i]);
return 0;
}
関連するオブジェクトにメソッドがある場合を除いて、循環参照が検出されるというステートメントがあります__del__()
。
あなたは正しいです — Python のサイクル検出器は、メソッドを持つオブジェクトが含まれていない限り、サイクルを検出して収集できます__del__
。これは、インタープリターがこれらのオブジェクトを安全に削除する方法がないためです (理由を直感的に理解するために、2 つのオブジェクトがあると想像してください)。__del__
相互に参照するメソッドで解放する必要があります。どの順序で解放する必要がありますか?)
メソッドを持つオブジェクトが__del__
サイクルに関与する場合、ガベージ コレクターはそれらを個別のリスト ( からアクセス可能gc.garbage
) に貼り付けて、プログラマーが手動で「処理」できるようにします。