すべてのコンピューター言語には独自の自動ガベージ コレクション メカニズムがあるため、プログラマーはプログラムのメモリ割り当てについてあまり心配する必要はありません。PHP も例外ではありません。ただし、オブジェクト指向プログラミング (OOP) プログラミングでは、一部のオブジェクトで必要なメモリが必要になります。プログラム実行メモリがオーバーフローしないようにします。
1. PHP ガベージコレクション機構 (ガベージコレクター (GC))
PHP では、このオブジェクトを指す変数がない場合、このオブジェクトはガベージになります。 PHP はこれをメモリ内で破棄します。これは、メモリのオーバーフローを防ぐための PHP の GC ガベージ処理メカニズムです。 PHP スレッドが終了すると、現在占有されているすべてのメモリ領域が破棄され、現在のプログラム内のすべてのオブジェクトが同時に破棄されます。 GC プロセスは通常、各 SESSION で実行を開始します。 gc の目的は、セッション ファイルの有効期限が切れた後に自動的に破棄および削除することです。
2. __破壊/設定解除
__destruct() デストラクターは、ガベージ オブジェクトがリサイクルされるときに実行されます。設定を解除すると、オブジェクトではなく、オブジェクトを指す変数が破壊されます。
3. セッションと GC
PHP の動作メカニズムにより、セッション情報を定期的にスキャンして無効かどうかを判断するデーモン スレッドがありません。有効なリクエストが発生した場合、PHP はグローバル変数セッションの値に基づいて判断します。 .gc_probability および session.gc_divisor 。デフォルトでは、session.gc_probability=1、session.gc_divisor =100 は、GC が開始される可能性が 1% であることを意味します (つまり、100 件のリクエストに 1 つの gc のみが開始されます)。リクエストに応じてアクティブ化された 100 リクエストのいずれかを伴う)。
GC の仕事は、すべてのセッション情報をスキャンし、現在の時刻からセッションの最終変更時刻を減算し、それを session.gc_maxlifetime パラメータと比較することです。生存時間が gc_maxlifetime (デフォルトは 24 分) を超える場合、セッションは終了します。削除される。ただし、Web サーバーに複数のサイトがある場合、GC が動作しているときに、異なるサイトのセッションが区別されないため、複数のサイトでセッションを処理すると、予期しない結果が発生する可能性があります。
それでは、この時点でそれを解決するにはどうすればよいでしょうか?
以下の例を見てください:
例 1: gc.php
リーリー言うまでもなく、% php -f gc.php の出力は非常に明確です:
リーリーさて、次は:
リーリー実行結果はまだ明らかです:
リーリーぜひご覧ください:
リーリーそれについて考える必要がありますか?
リーリーもう一度見てください:
リーリー実際、例 3 を理解していれば、これも同じです。
リーリーここを見てください:
リーリー最初の激しさは何ですか?
リーリーはい、これが出力結果です。すでに PHP GC を深く理解している PHP 使用者にとっては、このコードを初めて実行したときは驚きましたが、理解が深まりました。 PHP GC 理解しました。そうすれば、次のような同僚の例は自然に理解しやすくなります。
リーリーGC と参照を詳しく分析してみましょう:
すべての例で、変数が作成されます。簡単に言えば、このプロセスはメモリ内にスペースを開き、そこに文字列 I am test を格納します。 。 PHP 内には各メモリ ブロックの参照数を記録するシンボル テーブルがあり、このとき、このメモリ ブロックの参照数は 1 つ増加し、$a という名前のラベル (変数) がポイントされます。これは、メモリを操作するための名前のラベル付けに便利です。
変数 $a に対して & 演算を実行します。私の理解では、$a が指すメモリを見つけ、$b に対して同じ参照ポイントを確立し、文字列 I am test を保存します。 シンボルテーブル内のメモリブロックの参照カウントが1増加します。つまり、スクリプトがこの行に到達すると、文字列 I am test が保存されます。 メモリの一部が 2 回参照されます。ここで強調すべきことは、& 操作はポインターではなく参照ポインターを確立するということです。同時に、UNIX と同様のファイル ソフト リンクを提案している人もいます。それはある程度理解できます: I am テストの文字を保存します。 メモリの一部は私たちの実際のファイルであり、変数 $a と $b は実際のファイルに対して確立されたソフト リンクですが、同じ実際のファイルを指します。したがって、例 2 で $b に値が割り当てられると、$a の値も変化することがわかります。これは、ソフト リンクを介してファイルを操作するのと似ています。
在 Example 3 与 4 中,进行了 unset() 操作。根据实际的执行结果,可以看出: unset() 只是断开这个变量对它原先指向的内存的引用,使变量本身成为没有定义过空引用,所在调用时发出了 Notice ,并且使那块内存在符号表中引用计数 减 1,并没有影响到其他指向这块内存的变量。换言之,只有当一块内存在符号表中的引用计数为 0 时, PHP 引擎才会将这块内存回收。
看看下面的代码与其结果:
<?php error_reporting(E_ALL); $a = 'I am test.'; $b = & $a; unset($a); unset($a); unset($a); echo '$a = '. $a ."n"; echo '$b = '. $b ."n"; ?>
输出:
hy0kl% php -f gc.php Notice: Undefined variable: a in /usr/local/www/apache22/data/test/gc.php on line 10 $a = $b = I am test.
第一次 unset() 的操作已经断开了指向,所以后继的操作不会对符号表的任何内存的引用记数造成影响了。
赋值 null操作是相当猛的,它会直接将变量所指向的内存在符号号中的引用计数置 0,那这块内存自然被引擎回收了,至于何时被再次利用不得而知,有可能马上被用作存储别的信息,也许再也没有使用过。但是无论如何,原来所有指向那块内存变量都将无法再操作被回收的内存了,任何试图调用它的变量都将返回 null。
<?php error_reporting(E_ALL); $a = 'I am test.'; $b = & $a; $b = null; echo '$a = '. $a ."n"; echo '$b = '. $b ."n"; if (null === $a) { echo '$a is null.'; } else { echo 'The type of $a is unknown.'; } ?>
输出:
hy0kl% php -f gc.php $a = $b = $a is null.
综上所述,充分说明了为什么我们在看开源产品源码的时候,常看到一些比较大的临时变量,或使用完不再调用的重用信息都会被集中或显示的赋值为 null 了。它相当于 UNIX 中直接将真实文件干掉了,所有指向它的软链接自然成了空链了。
之前在讨论到这些细节点时有很多想当然的念头,在实际的执行了测试代码后才发现: 哦,原来如此!纸上得来终觉浅,绝知此事须躬行。