PHP変数のメモリ管理

不言
不言オリジナル
2018-04-18 10:11:101936ブラウズ

この記事では主に PHP 変数のメモリ管理を紹介します。これには特定の参照値が含まれています。必要な友達はそれを参照してください。

すべてのコンピューター言語は変数データを保存するためにいくつかのコンテナーを必要とします。一部の言語では、変数には文字列、配列、オブジェクトなどの特定の型があります。たとえば、C と Pascal はこのカテゴリに分類されます。 PHP にはそのような型はありません。 PHP では、ある行では文字列である変数が、次の行では数値になることがあります。多くの場合、変数は異なる型間で簡単に、さらには自動的に変換できます。 PHP がシンプルかつ強力な言語である理由の大部分は、変数の型指定が弱いためです。しかし、これが興味深い問題を引き起こす場合があります。

PHP 内部では、変数は zval と呼ばれるコンテナーに保存されます。これには、変数の値だけでなく、変数の型も含まれます。 PHP と同様に、Python にも変数の型をマークするラベルがあります。変数コンテナには、Zend エンジンが参照されているかどうかを区別するために使用するフィールドがいくつか含まれています。この値の参照カウントも含まれます。

変数は連想配列と同等のシンボルテーブルに格納されます。この配列は変数名をキーとしており、これらの変数を含むコンテナーを指します。以下に示すように:


参照カウント

PHP は、変数 ($a = $b など) をコピーする際に賢明であるように努めます。 「=」は代入演算子とも呼ばれます。代入操作を実行するとき、Zend エンジンは新しい変数ウィンドウを作成しませんが、変数ウィンドウの refcount フィールドを増やします。この変数が巨大な文字列または巨大な配列である場合、メモリの量が増加することが想像できます。保存されました。以下の図に示すように:


ステップ 1: 変数 a にはテキスト「this is」が含まれます。デフォルトでは、参照カウントは 1 に等しくなります

ステップ 2: 変数 $a を $b と $c に割り当てます。ここでは新しい変数コンテナは生成されません。変数が割り当てられるたびに refcount が 1 ずつ増加するだけです。ここでは 2 つの代入演算が実行されるため、最終的に refcount は 3 になります。

さて、変数 $c が変化すると何が起こるか疑問に思われるかもしれません。 refcount の値に応じて、2 つの異なる方法で処理されます。 refcount が 1 に等しい場合、変数コンテナはその値 (おそらくその型も) を更新します。 refcount が 1 より大きい場合、新しい値 (および型) を含む変数コンテナーが作成されます。図 2 の 3 番目のステップに示すように、$a 変数が配置されている変数コンテナーの refcount 値は 1 減算され、新しく作成されたコンテナーの refcount 値は 1 になります。 unset 関数が変数に対して使用されると、図のステップ 4 に示すように、変数が配置されているコンテナーの refcount 値が 1 つ減ります。 refcount の値が 1 未満の場合、図のステップ 5 に示すように、Zend エンジンは変数コンテナを変換します。

関数に変数を渡す

すべてのスクリプトで共有されるグローバル シンボル テーブルに加えて、各ユーザー定義関数は、独自の変数を保存するために呼び出されたときに独自のシンボル テーブルを作成します。関数が呼び出されると、Zend エンジンはそのようなシンボル テーブルを作成し、関数が返されるときに関数テーブルが解放されます。関数は return ステートメントを通じて戻るか、関数の終了によって戻ります (翻訳者注: 戻らない関数はデフォルトで NULL を返します)。下の写真に示すように:


図 3 は、変数が関数に渡される方法を詳しく示しています。

最初のステップでは、「thisis」を変数 $a に代入し、この変数を do_something() 関数の $s 変数に渡します。

2 番目のステップでは、これが別のシンボル テーブル (関数シンボル テーブル) に格納されることを除いて、変数の割り当て (前のセクションで説明した $b = $a と同様) と同じ操作であることがわかります。 ) となり、参照カウントは 1 ではなく 2 ずつ増加します。その理由は、関数スタックにはこの変数コンテナへの参照も含まれているためです。

3 番目のステップでは、変数 $s に新しい値を割り当てると、元の変数コンテナーの refcount が 1 減らされ、新しい値を含む変数コンテナーが作成されます。

4 番目のステップでは、return ステートメントを通じて変数を返します。返された変数は、グローバル シンボル テーブルからエンティティを取得し、その refcount を 1 ずつ増やします。関数が終了すると、関数のシンボル テーブルは破棄されます。破棄プロセス中に、Zend エンジンはシンボル テーブル内の各変数を調べて、その refcount 値を減らします。変数コンテナのリカウント値が0になると、変数コンテナは破棄されます。ご覧のとおり、PHP の参照カウント メカニズムにより、変数コンテナーは関数からコピーされません。変数 $s が 3 番目のステップで変更されていない場合、変数 $a と $b は常に同じ変数コンテナーを指します (このコンテナーの refcount は 2)。この場合、ステートメント $a = "this is" は変数コンテナのコピーを作成しません。

関連する推奨事項:

php変数のコピーオンライトメカニズム


以上がPHP変数のメモリ管理の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。