Python には、参照カウントのインクリメントやデクリメントを処理する二つの
マクロ、Py_INCREF(x)
と Py_DECREF(x)
があります。
Py_DECREF() は、参照カウントがゼロに到達した際に、
オブジェクトのメモリ解放も行います。
柔軟性を持たせるために、free() を直接呼び出しません --
その代わりにオブジェクトの型オブジェクト (type object)
を介します。このために (他の目的もありますが)、全てのオブジェクトには
自身の型オブジェクトに対するポインタが入っています。
さて、まだ重大な疑問が残っています: いつ Py_INCREF(x)
や
Py_DECREF(x)
を使えばよいのでしょうか?
まず、いくつかの用語説明から始めさせてください。
まず、オブジェクトは ``占有 (own)'' されることはありません;
しかし、あるオブジェクトに対する参照の所有 own a reference
はできます。オブジェクトの参照カウントは、そのオブジェクトが
参照を所有を受けている回数と定義されています。
参照の所有者は、参照が必要なくなった際にPy_DECREF()
を呼び出す役割を担います。参照の所有権は委譲 (transfer) できます。
所有参照 (owned reference) の放棄には、渡す、保存する、
Py_DECREF() を呼び出す、という三つの方法があります。
所有参照を処理し忘れると、メモリリークを引き起こします。
オブジェクトに対する参照は、借用 (borrow) も可能です。 1.2参照の借用者は、Py_DECREF() を呼んではなりません。 借用者は、参照の所有者から借用した期間を超えて参照を保持し続けては なりません。所有者が参照を放棄した後で借用参照を使うと、 解放済みメモリを使用してしまう危険があるので、絶対に避けねばなりません。 1.3
参照の借用が参照の所有よりも優れている点は、コードがとりうる あらゆる処理経路で参照を廃棄しておくよう注意しなくて済むことです -- 別の言い方をすれば、借用参照の場合には、処理の途中で関数を 終了してもメモリリークの危険を冒すことがない、ということです。 逆に、メモリリークの危険を冒すよりも不利な点は、ごくまともに 見えるコードが、実際には参照の借用元で放棄されてしまった後に その参照を使うかもしれないような微妙な状況があるということです。
Py_INCREF() を呼び出すと、借用参照を所有参照 に変更できます。この操作は参照の借用元の状態には影響しません -- Py_INCREF() は新たな所有参照を生成し、参照の所有者が 担うべき全ての責任を課します (つまり、新たな参照の所有者は、以前の 所有者と同様、参照の放棄を適切に行わねばなりません)。