1

Python オブジェクトを既存のメモリに初期化する正しい方法は何ですか (C++ の inplace new のように)

このコードを試してみましたが、_ob_prev と _ob_next が設定されていないため、デバッグ ビルドでアクセス違反が発生します。

//PyVarObject *mem; -previously allocated memory

Py_INCREF(type);
//couldnt get PyObject_HEAD_INIT or PyVarObject_HEAD_INIT to compile
//however the macros resolve to this
PyVarObject init = {{_PyObject_EXTRA_INIT 1, ((_typeobject*)type)}, 0};
*mem = init;
//...other init code for type...

object.c の 1519 行目でクラッシュが発生します。

void
_Py_ForgetReference(register PyObject *op)
{
#ifdef SLOW_UNREF_CHECK
        register PyObject *p;
#endif
    if (op->ob_refcnt < 0)
        Py_FatalError("UNREF negative refcnt");
    if (op == &refchain ||
        op->_ob_prev->_ob_next != op || op->_ob_next->_ob_prev != op) { //----HERE----//
        fprintf(stderr, "* ob\n");
        _PyObject_Dump(op);
        fprintf(stderr, "* op->_ob_prev->_ob_next\n");
        _PyObject_Dump(op->_ob_prev->_ob_next);
        fprintf(stderr, "* op->_ob_next->_ob_prev\n");
        _PyObject_Dump(op->_ob_next->_ob_prev);
        Py_FatalError("UNREF invalid object");
    }
#ifdef SLOW_UNREF_CHECK
    for (p = refchain._ob_next; p != &refchain; p = p->_ob_next) {
        if (p == op)
            break;
    }
    if (p == &refchain) /* Not found */
        Py_FatalError("UNREF unknown object");
#endif
    op->_ob_next->_ob_prev = op->_ob_prev;
    op->_ob_prev->_ob_next = op->_ob_next;
    op->_ob_next = op->_ob_prev = NULL;
    _Py_INC_TPFREES(op);
}
4

3 に答える 3

1

何をしているのかはかなりひどいです。このコードパスが本当にパフォーマンスに重要でない限り、通常行われているようにオブジェクトをヒープに割り当てることをお勧めします。

于 2009-12-27T01:32:02.343 に答える
0

額面通りに質問をすると、いくつかの選択肢があります。手っ取り早い方法は、初期化コードに追加のPy_INCREFを追加することです。refcountのバグがないと仮定すると、refcountがゼロに戻ることはなく、割り当て解除コードが呼び出されることもありません。また、クラッシュすることもありません。(実際、これは静的に割り当てられた組み込み型オブジェクトを管理する方法である可能性があります!)

好みの方法でメモリを管理する、タイプに合わせたカスタムアロケータとデアロケータを作成できます。実際、Pythonインタープリター全体のカスタムアロケーターとデアロケーターを作成することができます。

Pythonオブジェクトは通常の方法で管理できますが、自分で管理しているメモリ内のデータへのポインタをPythonオブジェクトに格納します。

全体像を見て...なぜあなたはこれをやろうとしているのですか?

また、あなたのコメントは

このコードを試しましたが、_ob_prevと_ob_nextが設定されていないため、デバッグビルドでアクセス違反が発生します。

//couldnt get PyObject_HEAD_INIT or PyVarObject_HEAD_INIT to compile
//however the macros resolve to this

心配しています!より高度なものに移る前に、標準のメモリ管理を使用するタイプを正常に定義しましたか?

于 2009-02-26T00:38:03.287 に答える
0

これがどのように行われるかについては、Py_NoneStruct を参照してください。あなたのコードは基本的に正しく見えます。

これは参照カウントのバグです。静的に割り当てられたオブジェクトは決して解放できないため、_Py_ForgetReference を呼び出すべきではありません。

それらを解放できるようにする場合は、静的初期化の代わりにカスタム アロケーターを使用する必要があります。

于 2009-03-30T21:35:31.530 に答える