一般的に言えば、スクリプト言語を使用する最大の利点の 1 つは、自動ガベージ コレクション メカニズムを使用してメモリを解放できることです。変数を使用した後にメモリを解放する処理は PHP が自動的に実行するため、何も行う必要はありません。
もちろん、必要に応じて unset() 関数を呼び出してメモリを解放することもできますが、通常はこれを行う必要はありません。
ただし、PHP では、unset() を手動で呼び出した場合でも、メモリが自動的に解放されない状況が少なくとも 1 つあります。詳細については、PHP 公式 Web サイト http://bugs.php.net/bug.php?id=33595 のメモリ リークの分析を参照してください。
問題の症状は次のとおりです:
「親オブジェクト-子オブジェクト」など、2 つのオブジェクト間に相互参照関係がある場合、親オブジェクトで unset() を呼び出しても、子オブジェクトで親オブジェクトを参照しているメモリは解放されません (親オブジェクトがガベージが収集されました。どちらも無理です)。
少し混乱していますか?次のコードを見てみましょう:
このコードを実行すると、メモリ使用量が枯渇するまでどんどん増加することがわかります。
ほとんどの PHP プログラマーにとって、この状況は問題ではありません。ただし、実行時間の長いコードで相互参照するオブジェクトを多数使用する場合、特にオブジェクトが比較的大きい場合は、メモリがすぐに使い果たされてしまいます。
ユーザーランドソリューション
少し面倒で洗練されていませんが、前述の bugs.php.net リンクに解決策が記載されています。
このソリューションでは、オブジェクトを解放する前にデストラクター メソッドを使用して、この目標を達成します。 Destructor メソッドはすべての内部親オブジェクト参照をクリアできます。これは、そうでなければオーバーフローするメモリのこの部分を解放できることを意味します。
「修正された」コードは次のとおりです:
新しい Foo::__destruct() メソッドと、オブジェクトを解放する前の $foo->__destruct() の呼び出しに注意してください。このコードはメモリ使用量の増加の問題を解決し、コードが正常に動作できるようになりました。
PHP カーネル ソリューション
なぜメモリオーバーフローが発生するのですか?私は PHP カーネルの研究には詳しくありませんが、この問題は参照カウントに関連していると確信しています。
この時点では、親オブジェクト $foo が解放されるため、PHP は $foo オブジェクトがまだ必要であると判断し、メモリのこの部分を解放しません。原理はほぼ同じです。
平たく言えば、一般的な意味は次のとおりです。参照カウントはデクリメントされないため、一部のメモリは決して解放されません。
さらに、前述の bugs.php.net リンクでは、ガベージ コレクション プロセスを変更すると優れたパフォーマンスが犠牲になるため、読者はこれに注意する必要があると指摘しています。
ガベージ コレクション プロセスを変更する代わりに、unset() を使用して内部オブジェクトを解放してみてはいかがでしょうか? (またはオブジェクトを解放するときに __destruct() を呼び出しますか?)
おそらく、PHP カーネル開発者は、このガベージ コレクション メカニズムをここまたは他の場所で変更できるでしょう。
この記事で説明されている内容は、誰もが PHP の動作原理を深く理解するのに役立つと信じています。
class Fruit{
protected $con = array();
function aa(){
$this->con[0] = new Apple();
$this->con[1] = new Banana( );
echo $this->con[0]->sweet;
}
}
疑わしいオブジェクトの参照を弱い参照に変更してみてください。弱い参照はメモリ オーバーフローの問題を非常にうまく解決できます。