PHP は自動的にメモリを管理し、不要になったオブジェクトを消去できます。 PHP は、単純なガベージ コレクション メカニズムである参照カウントを使用します。各オブジェクトには参照カウンタが含まれており、オブジェクトに接続されている参照ごとにカウンタが 1 ずつ増加します。参照がリビング スペースを離れるか、NULL に設定されると、カウンターは 1 ずつ減らされます。オブジェクトの参照カウンタがゼロになると、PHP はそのオブジェクトを使用する必要がなくなったことを認識し、PHP 5.3 より前に使用されていたガベージ コレクション メカニズムは単純な「参照カウント」でした。各メモリ オブジェクトにはカウンタが割り当てられます。メモリ オブジェクトが変数によって参照されている場合、カウンタは +1 になり、カウンタ = 0 の場合、カウンタは -1 になります。使用されず、メモリ オブジェクトは破棄されます。
「参照カウント」には問題があります。つまり、2 つ以上のオブジェクトが相互に参照してリングを形成する場合、この時点でメモリ オブジェクトのカウンタは 0 に減りません。役に立たなくなりましたが、リサイクルできないため、メモリ リークが発生します;
PHP 5.3 以降、参照カウントに基づいた新しいガベージ コレクション メカニズムが使用され、メモリ リークを回避するためにメモリ オブジェクト内の参照リングの存在を検出するための複雑なアルゴリズムが実装されました。
php 変数は、「zval」という変数コンテナーに存在します。「zval」変数コンテナーには、変数の型と値が含まれており、また、変数が参照であるかどうかを示す 2 バイトの追加情報も含まれています。 "refcount" "この zval 変数コンテナーを指す変数の数。
xdebug がインストールされている場合は、xdebug_debug_zval() を使用して「zval」情報を表示できます。以下の通り:
$str = "www.bKjia.c0m";
結果:
(refcount=1, is_ref=0),
文字列「phpddt.com」(長さ=10)
「refcount」が 0 になるときに変数コンテナが破棄される場合のみ。変数を unset() すると、目的の「zval」の refcount が 1 減ります。数日前に発生した参照の設定解除について話しましょう 質問:
コードをコピー | |
$a = "ああ"; $b = & $a; unset($a); //echo $b; //aaa はここでも出力されます。xdebug_debug_zval で出力すると、理由がわかります xdebug_debug_zval("b"); 結果: b: (refcount=1, is_ref=0),文字列 'aaa' (長さ=3)
|
コードをコピー | |||||
$arr = array( 'a' => 'aaa', 'b' => "bbb" ); xdebug_debug_zval( 'arr' ); $arr['aaa'] = $arr['a']; xdebug_debug_zval( 'arr' ); ?>
結果: (refcount=1, is_ref=0), 配列 'a' => (refcount=1, is_ref=0),string 'aaa' (length=3) 'b' => (refcount=1, is_ref=0),string 'bbb' (length=3) 編曲: (refcount=1, is_ref=0), 配列 'a' => (refcount=2, is_ref=0),string 'aaa' (length=3) 'b' => (refcount=1, is_ref=0),string 'bbb' (length=3) 'aaa' => (refcount=2, is_ref=0),文字列 'aaa' (length=3)
上記では、単に unset、null、mysql_close、__destruct、xdebug_debug_zval を使用してから読み続けました
解放されるべきであるが解放されていないメモリがあるかどうかを確認するには、memory_get_usage 関数を呼び出してメモリ使用量を確認します。memory_get_usage 関数によって返されるメモリ使用量データはあまり正確ではありません。より正確で有益なメモリ使用量データを取得するには、PHP の xdebug 拡張機能を使用します。
上記は、A オブジェクトのインスタンス a が作成されるたびに、B オブジェクトのインスタンス b を作成し、同時に b が a を参照するようにする例を構築します。各 A オブジェクトは常に B 参照によって表され、各 B オブジェクトは同時にオブジェクト A によって参照されます。これが参照サイクルの生成方法です。 このコードを php5.2 環境で実行すると、メモリ使用量が単調に増加しており、A と B のデストラクタが実行された後、メモリが使用されるまで「A/B デストラクタ」情報が出力されないことがわかります。使い果たされました、「PHP 致命的エラー: 許容メモリ サイズ 134217728 バイトが使い果たされました (40 バイトを割り当てようとしました)」。 このコードを php5.3 環境で実行すると、メモリ使用量が上下することがわかりますが、制限を超えることはありません。また、プログラムは大量の「A/B desctruct」を出力します。デストラクタは と呼ばれます。 私の同僚のプログラムにはこの種の参照ループがあり、彼のスクリプトは実際にはphp5.2.3で実行されます。 simple_html_dom ツールには、simple_html_dom と simple_html_dom_node という 2 つのクラスがあり、前者には配列メンバー変数ノードがあり、配列内の各要素は simple_html_dom_node オブジェクトであり、各 simple_html_dom_node オブジェクトにはメンバー変数 dom があり、その値は次のとおりです。前の simple_html_dom オブジェクト - したがって、美しい参照ループが形成され、メモリ リークが発生します。解決策も非常に簡単です。つまり、simple_html_dom オブジェクトの使用が終了し、そのクリア関数を積極的に呼び出してそのメンバー変数ノードをクリアすると、ループが中断され、メモリ リークは発生しません。
1) ガベージコレクションのタイミング
循環参照検出は、特定の条件が満たされたときにトリガーされるため、上記の例では、使用されるメモリに大きな変動が見られますが、gc_collect_cycles 関数を通じて循環参照検出をアクティブに実行することもできます。 2) アンパサンドの影響 変数を明示的に参照すると、そのメモリの参照カウントが増加します: $a = "何か"; $b = &$a; この時点ではunset($a)していますが、メモリ領域を指す$bへの参照が残っており、メモリは解放されません。 3) unset関数の影響 unset は変数をメモリ領域から切断し、メモリ領域の参照カウントを -1 減らすだけです。上記の例では、ループ本体内では $a=new A(); は行われません。 $a の参照カウントをゼロに減らします ;4) = null 操作の影響 $a = null は、$a が指すデータ構造を直接 null にし、その参照カウントを 0 に返します。 5) スクリプト実行終了の影響 スクリプトの実行が終了すると、参照サイクルの有無に関係なく、スクリプトで使用されていたすべてのメモリが解放されます。
前の記事:PHP定期検証日時フォーマットサンプルコード_PHPチュートリアル
次の記事:PHP で isset を使用する場合は、配列に key_PHP チュートリアルがあるかどうかを確認するために注意して使用してください。
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
著者別の最新記事
最新の問題
URL パラメータから取得した PHP 配列が期待どおりに動作しない
カテゴリ ID を含む URL パラメータがあり、それを次のような配列として扱いたいと考えています: http://example.com?cat[]=3,9,13 PHP では、...
から 2024-04-06 22:09:02
0
1
1428
戻り値の変数の形式は何ですか?
私はphpの初心者です。コードを見つけました: if($x<time()){return[false,'error'];} ロジックや変数は重要ではありませんが、[false...
から 2024-04-06 21:55:20
0
1
778
ループするために MySQL の結果を ID ごとにグループ化する
mysqlにフライトデータを含むテーブルがあります。 codeigniter3Journey_idair_idFlightDurationout_or_inflightdurati...
から 2024-04-06 17:27:56
0
1
406
関連トピック
詳細>
|