2013-03-08 152 views

回答

20

如果缺少Py_INCREF将导致对Py_None的引用计数错误,这可能导致解释程序释放Py_None。由于Py_NoneObjects/object.c文件静态分配:

PyObject _Py_NoneStruct = { 
    _PyObject_EXTRA_INIT 
    1, &PyNone_Type 
}; 

而在Include/object.h存在定义:

#define Py_None (&_Py_NoneStruct) 

那么会发生什么,是解释器将致命错误崩溃:

Fatal Python error: deallocating None 

这是none_dealloc函数生成的Objects/object.c

/* ARGUSED */ 
static void 
none_dealloc(PyObject* ignore) 
{ 
    /* This should never get called, but we also don't want to SEGV if 
    * we accidentally decref None out of existence. 
    */ 
    Py_FatalError("deallocating None"); 
} 

如前所述通过评论,如果NoneType没有自己的解除分配的功能,你会得到一个分段错误,因为free调用将栈上进行。

您可以在tutorial中测试这个复制示例,将Py_DECREF(Py_None)的调用添加到Noddy_name函数中,构建扩展并执行调用该方法的循环。


在一般情况下0引用计数可能会导致程序在许多不同的方式失败。

特别是python可以自由地重用被释放的对象所使用的内存,这意味着对象的每个引用都可以成为对一个随机对象(或空的内存位置)的引用,而你可以看到像:

>>> None #or whatever object that was deallocated 
<ARandomObjectYouNeverSawBefore object at ...> 

(有时这实际上happened对我来说,写C扩展时,这里变成读一些对象只有在缓冲由于缺少呼叫Py_INCREF随机倍)。

在其他情况下,可能会引发不同类型的错误,或解释器可能崩溃或段错误。

+0

'PyNone'可能是静态分配(不Python源我来看看它),所以我们试着释放静态分配的内存,这将是特别有趣的..在任何情况下都没有什么好处。 – Voo 2013-03-08 08:05:02

+0

@Voo我也这么认为,事实证明它是静态分配的(在'object.c'中),这导致了一个致命的错误。无论如何,我的推理是正确的,只是它更适合忘记增加一个通用对象。 – Bakuriu 2013-03-08 10:57:01

14

Py_None实际上只是另一个Python对象,除非没有方法。

Python会计算对任何PyObject*的引用。无论它是字符串,整数还是无。

如果不增加引用计数,Python解释器会在其引用计数达到0后最终放弃该对象,因为它认为没有任何指向该对象的指针。这意味着下一次您尝试使用返回值执行某些操作时,您将会看到一个指向内存中的位置的指针,该位置不保证为Py_None(错误,奇怪的值,分段错误等)。

有替代品必须记住使用Py_INCREF(Py_None)

return Py_BuildValue(""); 

Py_RETURN_NONE; 
相关问题