1.2.1 参照カウント

今日の計算機は有限の (しばしば非常に限られた) メモリサイズしか 持たないので、参照カウントは重要な概念です; 参照カウントは、 あるオブジェクトに対して参照を行っている場所が何箇所あるか を数える値です。参照を行っている場所とは、別のオブジェクトで あったり、グローバルな (あるいは静的な) C 変数であったり、 何らかの C 関数内にあるローカルな変数だったりします。 あるオブジェクトの参照カウントがゼロになると、そのオブジェクトは 解放されます。そのオブジェクトに他のオブジェクトへの 参照が入っていれば、他のオブジェクトの参照カウントはデクリメント されます。デクリメントの結果、他のオブジェクトの参照カウント がゼロになると、今度はそのオブジェクトが解放される、といった具合に 以後続きます。(言うまでもなく、互いを参照しあうオブジェクトに ついて問題があります; 現状では、解決策は ``何もしない'' です。)

参照カウントは、常に明示的なやり方で操作されます。 通常の方法では、Py_INCREF() でオブジェクトの参照を 1 インクリメントし、 Py_DECREF() で 1 デクリメント します。Py_DECREF() マクロは、incref よりもかなり 複雑です。というのは、Py_DECREF() マクロは参照カウント がゼロになったかどうかを調べて、なった場合にはオブジェクトの デアロケータ (deallocator) を呼び出さなければならないからです。 デアロケータとは、オブジェクトの型を定義している構造体内にある 関数へのポインタです。 型固有のデアロケータは、その型が複合オブジェクト (compound object) 型である場合には、オブジェクト内の他のオブジェクトに対する参照 カウントをデクリメントするよう気を配るとともに、その他の必要な ファイナライズ (finalize) 処理を実行します。 参照カウントがオーバフローすることはありません; というのも、 仮想メモリ空間には、(sizeof(long) >= sizeof(char*) と 仮定した場合) 少なくとも参照カウントの記憶に使われるビット数と 同じだけのメモリ上の位置があるからです。従って、参照カウントの インクリメントは単純な操作になります。

オブジェクトへのポインタが入っているローカルな変数全てについて、 オブジェクトの参照カウントを必ずインクリメントしなければならない わけではありません。理論上は、オブジェクトの参照カウントは、 オブジェクトを指し示す変数が生成されたときに 1 増やされ、 その変数がスコープから出て行った際に 1 減らされます。しかしこの 場合、二つの操作は互いに相殺するので、結果的に参照カウントは 変化しません。参照カウントを使う真の意義とは、手持ちの何らかの 変数がオブジェクトを指している間はオブジェクトがデアロケート されないようにすることにあります。オブジェクトに対して、 一つでも別の参照が行われていて、その参照が手持ちの変数 と同じ間維持されるのなら、参照カウントを一時的に増やす必要は ありません。参照カウント操作の必要性が浮き彫りになる重要な局面 とは、Python から呼び出された拡張モジュール内の C 関数に オブジェクトを引数として渡すときです; 呼び出しメカニズムは、 呼び出しの間全ての引数に対する参照を保証します。

しかしながら、よく陥る過ちとして、あるオブジェクトをリストから 得たときに、参照カウントをインクリメントせずにしばらく放っておく というのがあります。他の操作がオブジェクトをリストから除去してしまい、 参照カウントがデクリメントされてデアロケートされてしまうことが 考えられます。 本当に危険なのは、まったく無害そうにみえる操作が、上記の動作を 引き起こす何らかの Python コードを呼び出しかねないということです; Py_DECREF() からユーザへ制御を戻せるような コードパスが存在するため、ほとんど全ての操作が潜在的に危険を はらむことになります。

安全に参照カウントを操作するアプローチは、汎用の操作 (関数名が "PyObject_", "PyNumber_", "PySequence_", および "PyMapping_" で始まる関数) の利用です。これらの操作は 常に戻り値となるオブジェクトの参照カウントをインクリメントします。 ユーザには戻り値が不要になったら Py_DECREF() を呼ぶ 責任が残されています; とはいえ、すぐにその習慣は身に付くでしょう。



ご意見やご指摘をお寄せになりたい方は、 このドキュメントについて... をご覧ください。