PHP 拡張機能を作成するには、PHP カーネル内の変数の表現に触れることが避けられないため、PHP 変数がカーネル内でどのように保存され、使用されるかを理解する必要があります。
PHP 変数がカーネルに格納される仕組み
PHP は弱い型指定言語です。つまり、PHP 変数はあらゆるデータ型を保存できますが、PHP はこのため、Zend エンジンの変数構造は次のようになります:
PHP カーネル変数アクセス マクロ
変数の型を設定するには、zval.type = IS_LONG を使用します。ただし、PHP の将来のバージョンでどのような変更が発生するかを予測することは不可能であるため、これはあまり適切ではありません。 type 変数の名前を type_gc または Others に変更すると、以前に作成された拡張機能がこれらのバージョンに適応できなくなります。この問題を解決するために、PHP カーネルは次のような変数の型にアクセスして設定するメソッドを提供します。 zval) zval 構造体に対応 エンティティ
Z_TYPE(&zval) は zval 構造体のポインタに対応
Z_TYPE(&&zval) は zval 構造体の二次ポインタに対応
次の方法で変数の型を設定できます: Z_TYPE(zval) = IS_LONG この方法では、zval 構造体の型メンバー変数の名前が将来変更された場合でも、拡張機能は引き続き使用できます。変数の型、変数の値には、次のような対応するアクセス マクロ定義もあります。 Z_LVAL(zval) = 10 ;値 10 を変数に割り当てます。
上記の zval 構造体から、zval 構造体には参照カウンター用の 2 つのメンバー変数があることがわかります:
is_ref: bool、変数が参照セットであるかどうかを識別します
refcount: 参照コレクションを指す変数の数をカウントします
$a = 'これは変数です';
$b = $a;
上記のコードは 2 つの変数 $a と $b を作成します。PHP7.0 では、変数 b が a の値をハードコピーするため、zval の is_ref が PHP カーネル内に作成されます。 $a に対応するコンテナは FALSE であり、refcount は 1 です。しかし、PHP5.6 バージョン (およびそれ以前?) では、 a の is_ref は FALSE です。これは、 b が a を参照するのではなく、 の refcount を参照するためです。この時点では a は 2 です。これは PHP5.6 のバージョン (それ以前?) のコピー オン ライト (コピー オン ライト) の仕組みによるもので、PHP7.0 と PHP5.6 を使用したテスト結果がこれを証明しています。
時限コピーは、値が同じ場合、新しい変数を保存するために新しいメモリを作成せず、新しい変数をメモリ アドレスに参照する方法です。変数の値が異なる場合のみメモリがコピーされます。実際、時限コピーも参照の一種ですが、この種の参照は変数の値が変化すると破棄されてしまいます。
変数が別の変数によって明示的に参照されると、変数の is_ref フィールドは 1 に設定され、変数が参照されていることを示し、参照カウンターもそれに応じて 1 増加します。