3

Python コールバックを使用する C++ ライブラリがあります。コールバック、つまり PyObject* はクラス UnaryFunction のオブジェクトに格納され、コンストラクタ Py_INCREF がそれを呼び出します。デスタクタ Py_XDECREF はそれを参照します。それが問題です。インタープリターは、その DECREF でセグメンテーション違反を起こします。

私の解決策は、DECREFしないことですが、それは間違っているようです。関数の参照カウントを INC/DEC する適切な方法は何ですか? さらに重要なことに、他のライブ参照があるときにインタープリターが関数本体を GC しようとするのはなぜですか?

編集: Linux では、セグメンテーション違反の代わりに、次のようなアサーション失敗が発生します。

python: Objects/funcobject.c:442: func_dealloc: Assertion 'g->gc.gc_refs != (-2)' failed.

4

2 に答える 2

1

クラッシュは、使用済みオブジェクトをGCしようとしていることを意味する必要はありません。また、インタプリタロックなしでPythonコードを呼び出していることを意味する場合もあります。

デストラクタでPy_XDECREFを呼び出すと、次のようなものがあると思います。

void MyCallback(myfunc, myarg)
{
    ...
    PyGILState_STATE gilstate = PyGILState_Ensure();
    try {
            myfunc(myarg);
    } catch (...) {
        ...
    }
    PyGILState_Release(gilstate);

    // myfunc goes out of scope here --> CRASH because we no longer own the GIL
}

簡単な解決策で:

...
try {
    scopefunc = myfunc;
    myfunc = emptyfunc();
    scopefunc(myarg);
} ...
于 2011-09-08T03:47:07.423 に答える
0

Py_INCREF は実際には参照カウントをインクリメントしていないようです。

于 2011-09-09T00:12:35.850 に答える