1

将python对象初始化到已经存在的内存中的正确方法是什么(如c ++中的就地新)

我尝试了此代码,但是由于未设置 _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

Taking your question at face value, you have a few options. The quick and dirty method is to put an extra Py_INCREF into your initialisation code. Assuming you have no refcount bugs, the refcount will never return to zero, deallocation code will never be called, and there should be no crash. (In fact this may be the way that the statically allocated builtin type objects are managed!)

You could write a custom allocator and deallocator for your type that manages memory in your preferred manner. You could in fact write a custom allocator and deallocator for the whole python interpreter.

You could manage your python objects in the normal way but store pointers in them to data in the memory you are managing yourself.

Looking at the bigger picture... why are you trying to do this?

Also, your comments that

I tried this code however it causes an access violation with a debug build because the _ob_prev and _ob_next are not set..

and

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

are worrying! Have you successfully defined a type which uses standard memory management, before moving on to more advanced stuff?

于 2009-02-26T00:38:03.287 回答
0

您可以查看 Py_NoneStruct 以了解这是如何完成的。您的代码看起来基本正确。

这是一个引用计数错误。静态分配的对象永远不能被释放,所以永远不应该调用 _Py_ForgetReference。

如果您希望能够释放它们,则必须使用自定义分配器而不是静态初始化。

于 2009-03-30T21:35:31.530 回答