9

SWIGを使用して PHP 拡張機能を作成しましたが、すべて正常に動作しますが、メソッド呼び出しを連鎖させると、奇妙なガベージ コレクション動作が見られます。たとえば、これは機能します:

$results = $response->results();
$row = $results->get(0)->iterator()->next();
printf('%s %s' . "\n", $row->getString(0), $row->getString(1));

しかし、このセグメントは失敗します:

$row = $response->results()->get(0)->iterator()->next();
printf('%s %s' . "\n", $row->getString(0), $row->getString(1));

唯一の違いは、最初は を作成する$resultsのに対し、2 番目は呼び出しを連鎖させることです。

SWIG は実際には関数を PHP に公開するだけで、それらと対話するための PHP プロキシ クラスを生成します。これらのプロキシ クラスは、基本的に、公開された各関数に渡されるリソースを、それらの関数が通常取る他の引数と共に保持します。おそらくこれらのプロキシ クラスが問題であると考えて、コードを作り直してそれらをバイパスし、代わりに公開された関数を直接使用しました。前と同じように、これは機能します:

$results = InvocationResponse_results($response->_cPtr);
$row = TableIterator_next(Table_iterator(Tables_get($results, 0)));
printf('%s %s' . "\n", Row_getString($row, 0), Row_getString($row, 1));

繰り返しますが、このセグメントは失敗します:

$row = TableIterator_next(Table_iterator(Tables_get(InvocationResponse_results($response->_cPtr), 0)));
printf('%s %s' . "\n", Row_getString($row, 0), Row_getString($row, 1));

繰り返しますが、唯一の違いは、最初は を作成する$resultsのに対し、2 番目は呼び出しを連鎖させていることです。

この時点で、gdb/valgrind でしばらくデバッグを行ったところ、InvocationResponse_results呼び出しをチェーンするときに戻り値のデストラクタが呼び出されるのが早すぎることがわかりました。観察するためにstd::cout、公開された C++ 関数とそのデストラクタの先頭にステートメントを挿入しました。これは連鎖なしの出力です:

InvocationResponse_results()
Tables_get()
Table_iterator()
TableIterator_next()
__wrap_delete_TableIterator
Row_getString()
Row_getString()
Hola Mundo
---
__wrap_delete_InvocationResponse
__wrap_delete_Row
__wrap_delete_Tables

スクリプト---の実行中と実行後に何が起こるかを区別できるように、スクリプトの最後に出力しました。Hola Mundoからprintfです。残りは C++ からのものです。ご覧のとおり、すべてが期待どおりの順序で呼び出されます。デストラクタはスクリプトの実行後にのみ呼び出されますが、TableIteratorデストラクタは予想よりも早く呼び出されます。ただし、これにより問題が発生することはなく、おそらく無関係です。これをチェーニングを使用した出力と比較します。

InvocationResponse_results()
Tables_get()
__wrap_delete_Tables
Table_iterator()
TableIterator_next()
__wrap_delete_TableIterator
Row_getString()
Segmentation fault (core dumped)

InvocationResponse_resultsに保存される戻り値がなければ、実行がコール チェーン (と$resultsの間) から出る前にガベージ コレクションが実行されるため、すぐに問題が発生し、最終的にはセグ フォールトにつながります。Tables_getTable_iterator

xdebug_debug_zval()また、いろいろなところで参照カウントを調べてみましたが、特に異常はありませんでした。以下は、チェーンを使用した場合$resultsと使用しない場合の出力です。$row

results: (refcount=1, is_ref=0)=resource(18) of type (_p_std__vectorT_voltdb__Table_t)
row: (refcount=1, is_ref=0)=resource(21) of type (_p_voltdb__Row)

そして$rowチェーンで:

row: (refcount=1, is_ref=0)=resource(21) of type (_p_voltdb__Row)

私はこれに数日を費やしましたが、アイデアがほとんどなくなったので、これを解決する方法についての洞察は大歓迎です。

4

1 に答える 1

1

これは、同様のデバッグ問題のsegfaultingの問題の一部であることが判明しました。(Artefactoが言ったこと)

于 2010-09-17T16:02:05.607 に答える