Python C-API对象初始化
将python对象初始化到现有内存(如c++中的inplace new)的正确方法是什么 我尝试了这段代码,但是由于没有设置_ob_prev和_ob_next,它会导致调试版本的访问冲突Python C-API对象初始化,python,c,python-3.x,python-c-api,Python,C,Python 3.x,Python C Api,将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
//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);
}
void
_Py_ForgetReference(寄存器PyObject*op)
{
#ifdef慢速检查
寄存器PyObject*p;
#恩迪夫
if(op->ob_refcnt<0)
Y_FatalError(“UNREF负参考”);
if(op==&refchain)||
在这里,{/------//
fprintf(stderr,“*ob\n”);
_PyObject_转储(op);
fprintf(标准,“*op->\U ob\U prev->\U ob\U next\n”);
_PyObject_Dump(op->u ob_prev->u ob_next);
fprintf(标准,“*op->\U ob\U next->\U ob\U prev\n”);
_PyObject_Dump(op->u ob_next->u ob_prev);
Py_FatalError(“UNREF无效对象”);
}
#ifdef慢速检查
对于(p=refchain.\u ob\u next;p!=&refchain;p=p->\u ob\u next){
如果(p==op)
打破
}
如果(p==&refchain)/*未找到*/
Py_FatalError(“UNREF未知对象”);
#恩迪夫
op->\U ob\U next->\U ob\U prev=op->\U ob\U prev;
op->\U ob\U prev->\U ob\U next=op->\U ob\U next;
op->\u ob\u next=op->\u ob\u prev=NULL;
_皮尤公司(op);
}
直面问题,你有几个选择。快速而肮脏的方法是在初始化代码中添加一个额外的Py_INCREF。假设您没有refcount错误,refcount将永远不会返回零,释放代码将永远不会被调用,并且不会出现崩溃。(实际上,这可能是管理静态分配的内置类型对象的方式!)
您可以为您的类型编写一个自定义分配器和释放定位器,以您喜欢的方式管理内存。实际上,您可以为整个python解释器编写一个自定义分配器和解除定位器
您可以以正常的方式管理python对象,但可以在其中存储指向您自己管理的内存中的数据的指针
从更大的角度来看。。。你为什么要这么做
还有,你的评论是
我尝试了这段代码,但是由于没有设置_ob_prev和_ob_next,它会导致调试版本的访问冲突。。
及
你在担心!您是否已成功定义了一种使用标准内存管理的类型,然后再转到更高级的内容?从表面上看,您有几个选择。快速而肮脏的方法是在初始化代码中添加一个额外的Py_INCREF。假设您没有refcount错误,refcount将永远不会返回零,释放代码将永远不会被调用,并且不会出现崩溃。(实际上,这可能是管理静态分配的内置类型对象的方式!) 您可以为您的类型编写一个自定义分配器和释放定位器,以您喜欢的方式管理内存。实际上,您可以为整个python解释器编写一个自定义分配器和解除定位器 您可以以正常的方式管理python对象,但可以在其中存储指向您自己管理的内存中的数据的指针 从更大的角度来看。。。你为什么要这么做 还有,你的评论是 我尝试了这段代码,但是由于没有设置_ob_prev和_ob_next,它会导致调试版本的访问冲突。。 及
你在担心!在转到更高级的东西之前,您是否成功定义了使用标准内存管理的类型?您可以查看Py_nonestuct了解如何实现这一点。您的代码看起来基本正确 这是一个计数错误。静态分配的对象永远无法释放,因此永远不应调用_Py_ForgetReference
如果您希望能够释放它们,则必须使用自定义分配器而不是静态初始化。您可以查看Py_nonestuct了解如何完成此操作。您的代码看起来基本正确 这是一个计数错误。静态分配的对象永远无法释放,因此永远不应调用_Py_ForgetReference
如果您想释放它们,必须使用自定义分配器,而不是静态初始化。我们正在做的事情非常可怕。除非这个代码路径真的对性能至关重要,否则我建议您像通常那样在堆上分配对象。正在做的事情非常可怕。除非此代码路径真的对性能至关重要,否则我建议您像通常那样在堆上分配对象。引用计数是正确的,而不是这里的问题(因此它在发布版本中工作正常)。问题是,在调试构建中,next和prev为null这一事实似乎会导致python在清理对象时崩溃,因此我似乎需要一种初始化它们的方法。我所有的类型都使用标准python内存管理(即不将tp_*类型的内容过度隐藏为内存,或使用PyObject_New*+PyObject_Del)可以正常工作(在debug和release中),我假设在所有这些情况下都设置了next和pefv指针,而这里没有。reference计数是正确的,而不是这里的问题(因此它在release构建中工作良好的原因)问题是,在调试构建中,当清理对象时,next和prev为null这一事实似乎会导致python崩溃,因此我似乎需要一种方法来初始化它们。我所有的类型都使用标准python内存管理(即不将tp_*类型的内容过度隐藏为内存,或使用PyObject_New*+PyObject_Del)可以正常工作(在debug和release中),我假设在所有这些情况下都设置了next和pefv指针,而这里没有。
//couldnt get PyObject_HEAD_INIT or PyVarObject_HEAD_INIT to compile
//however the macros resolve to this