私は、オブジェクトメソッドが配列zval
を返す必要があるPHP拡張を開発しています。コードが正常に動作し、期待されることを行いPHPエクステンションからメモリにコピーすることなく配列を返す方法は?
ZEND_METHOD(myObject, myMethod)
{
zval **myArrayProperty;
if (zend_hash_find(Z_OBJPROP_P(getThis()), "myArrayProperty", sizeof("myArrayProperty"), (void **) &myArrayProperty) == FAILURE) {
RETURN_FALSE;
}
RETURN_ZVAL(*myArrayProperty, 1, 0);
}
- それは、オブジェクトのmyArrayProperty
を返しますよう
方法が見えます。しかし、私はプロセスを最適化したいと思います。
myArrayProperty
は非常に大きい配列を格納します。そしてRETURN_ZVAL()
マクロは値を返すために配列を複製します。複製プロセスでは、メモリを取得してすべての配列値をコピーするのに時間がかかります。同時に、返された配列は通常、読み取り専用操作に使用されます。だから最適な最適化は、参照カウントでPHPのメカニズムを使用することであり、myArrayProperty
の内容を複製しません。むしろ、私はrefcount
をmyArrayProperty
に増やして、それにポインタを戻します。これは、PHP拡張モジュールで変数を扱うときに通常使用されるのと同じ方法です。
しかし、それを行う方法はないようです。PHP拡張機能から返すために値を複製する必要があります。関数のシグネチャを参照によって返すように変更することは、プロパティと戻り値をリンクするため、つまり戻り値を後で変更するとプロパティを変更するため、オプションではありません。それは容認できる行動ではありません。
function myMethod() {
{
return $this->myArrayProperty;
}
参照カウント機構によって最適化される:PHPで同じコードをので
参照カウントを係合することができないことは、奇妙に見えます。だからこそ私はStackOverflowでこの質問をしています。
したがって、メモリに配列をコピーせずに、PHP拡張モジュールの関数から配列を返す方法はありますか?
しかし、メモリリークやセグメンテーション(いずれか先に来る方)につながることはありませんか?メモリリークは、プロパティへのすべての参照がクリアされたときに発生しますが、refvalが1のままであるため、zvalコンテナが占有するメモリは解放できません。返された値が破棄されるとSegfaultが発生し、コンテナは配列(共有されたHashTable、そのコンテナとプロパティzvalコンテナの両方から参照されます)と一緒にクリアされるため、後でプロパティを使用すると、予測できない間違いがあります。 –
プロパティ参照zval - refcount = 1です。このコードは、zvalが返されたときにrefcountを増加させ、オブジェクトと呼び出し元の両方によって参照されます。オブジェクトがプロパティを必要としない場合、refcountが減少するので、呼び出し元だけが所有します。だから、このコードは私には正気に見えます。しかし、再び、これは厳密には理論的なものです - 私はPHPのソースを今でも開かれていません。 – JimiDini
残念ながら、予測通り、コードは動作しません - 実際には確認済みです:http://pastebin.com/FRfaJZvL。問題は上記の通りです:オブジェクトと呼び出し元は異なるメモリ位置を参照します。 –