PHP5 では、オブジェクト インスタンスごとに __destruct() メソッドが呼び出されることが保証されていますか? プログラムの例外により、これを防ぐことができますか?
6 に答える
独自のデストラクタを持つサブクラスの場合、親デストラクタは自動的に呼び出されないことにも注意してください。
親クラスが必要なクリーンアップを行う場合は、サブクラスの__destruct()メソッドからparent::__destruct()を明示的に呼び出す必要があります。
デストラクタは、すべての参照が解放されたとき、またはスクリプトが終了したときに呼び出されます。これは、スクリプトが正常に終了したときを意味すると思います。重大な例外は、デストラクタが呼び出されることを保証しません。
PHPのドキュメントは少し内容が薄いですが、デストラクタで例外が発生すると問題が発生すると書かれています。
私の経験では、デストラクタは常に PHP 5.3 で呼び出されますが、コードの一部が exit() を呼び出す場合、または致命的なエラーが発生した場合、PHP は「任意の」順序でデストラクタを呼び出すことに注意してください (実際の順序はメモリまたはメモリがオブジェクト用に予約された順序. 実際には、この順序はほとんど常に問題があります)。これは、PHP ドキュメントでは「シャットダウン シーケンス」と呼ばれています。
デストラクタの PHP ドキュメントには、次のように記載されています。
PHP 5 では、C++ などの他のオブジェクト指向言語と同様のデストラクタの概念が導入されています。デストラクタ メソッドは、特定のオブジェクトへの他の参照がなくなるとすぐに、またはシャットダウン シーケンス中に任意の順序で呼び出されます。
その結果、Y への参照を保持するクラス X がある場合、Y のデストラクタが既に呼び出された後に、X のデストラクタが呼び出される可能性があります。うまくいけば、Y への参照はそれほど重要ではありません... 文書化されているため、公式にはこれはバグではありません。
ただし、デストラクタが正常に呼び出されるか (デストラクタは正しい順序で呼び出されるか)、デストラクタが「任意の」順序で呼び出されるかどうかを知る方法が正式に提供されていないため、この問題を回避することは非常に困難です。すでに破壊されています。debug_backtrace() を使用してスタックを調べると、この検出の欠如を回避できます。通常のスタックがないということは、PHP 5.3 では「シャットダウン シーケンス」を暗示しているようですが、これも未定義です。循環参照がある場合、これらのオブジェクトのデストラクタは PHP 5.2 以前ではまったく呼び出されず、PHP 5.3 以降では「シャットダウン シーケンス」中に「任意の」順序で呼び出されます。循環参照の場合、論理的に「正しい」順序は存在しないため、「任意」
いくつかの例外があります (これは結局 PHP です)。
- 別のデストラクタで呼び出された場合
exit()
、残りのデストラクタは呼び出されません ( http://php.net/manual/en/language.oop5.decon.php ) - どこかで
FATAL
エラーが発生した場合 (他のデストラクタから例外をスローしようとするなど、多くの原因が考えられます)、残りのデストラクタは呼び出されません。
もちろん、PHP エンジンでセグメンテーション違反が発生したり、その他の内部バグが発生したりした場合、すべての賭けは無効になります。
「シャットダウン シーケンス」の現在の実装を理解したい場合は、 https://stackoverflow.com/a/14101767を参照してください。この実装は、将来の PHP バージョンで変更される可能性があることに注意してください。
暗黙的に呼び出される destruct メソッドを停止する循環参照に関する現在のバグがあります。http://bugs.php.net/bug.php?id=33595 5.3 で修正されるはずです
確実に行きたい場合は、シャットダウン関数を使用してください: register_shutdown_function()