2013-03-08 121 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; 
相關問題