著作一覧 |
参照判定という呼び方があるかどうかは知らないけど、コピー方式はマーク&スィープとは区別されていたように記憶しているし、いずれも有効な参照があるかどうかを判定するという点で、利用側がリファレンスカウンタを操作する方法とは区別されているから、そう分けてみた。
で、リファレンスカウント方式というと、僕は代表的な実装としてCOMを思い浮かべる。COMの場合、言語がVBであれば参照カウンターの処理は処理系が行い、プログラミング言語のソースには直接は示されない(だから、VBプログラムでCOMリークというのは目にしたことはない)、同じくソースコードに明示的に表れないものにJScriptがある。一方、C++の場合は、明示的にAddRef/ReleaseのAPIでカウンタを操作する。ただし、提供されたスマートポインタを使って気にしないことも可能だった。
が、COMで広範に参照カウンタ方式のGCを取り入れたMSが、約8年の実験の末に、.NET Frameworkでは参照方式に変更したわけで、彼らの選択は短期的には常に正しくないが、中長期的には常にうまいことやっているということを考えると、リファレンスカウンタ方式には問題があるのではないかということに思い当たる。
ひとつは、循環参照の問題で、有効な参照が残っているかどうかを判定するシステムであれば、すべての参照が無効となって回収できるはずだが、参照カウンタ方式ではカウンタ値が0にならない状態がある。Pythonの場合は循環参照検出機構を持つことで解決しているようだ。
より大きな問題として、マルチプロセス、マルチノードに及ぶオブジェクトシステムの考慮がある。ダウンしたノード、途中で消滅したプロセスから参照されているオブジェクトはカウンタを戻す機会を失う。そのためにpingをかけたり、大変なことになる。(大変さの例:Managing Object Lifetimes in OLE、なんていうものを持ち出すまでもなく、Win32OLEの実装をみればいかに面倒で、かつ例外的な状況が多いかがわかるかも)
で、最終的にMSはこんなことを言い出すことになった。
The reference counting scheme is the source of many bugs.
単純なシステムであれば、参照カウンタは確実だとは思うが、そんなに良いものではないのではないか、ということ。
ジェズイットを見習え |