2009-02-24 110 views
1

什麼是初始化一個Python對象到現有存儲器(類似於C的就地新++)Python的C-API對象初始化

我試過但是這個代碼它會導致訪問衝突與調試版本,因爲正確的方法在_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

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); 
} 

回答

0

以你的面值問題上線1519 occures,你有一個鐵w選項。快速和骯髒的方法是將額外的Py_INCREF放入初始化代碼中。假設你沒有refcount錯誤,refcount永遠不會回到零,deallocation代碼永遠不會被調用,並且不應該崩潰。 (事實上​​,這可能是靜態分配內建類型對象的管理方式!)

你可以寫你的類型,在您的首選方式管理存儲自定義分配器和釋放器。實際上你可以爲整個python解釋器編寫一個自定義分配器和釋放器。

你可以在他們管理的正常方式你的Python對象,但指針存儲在您管理自己的存儲數據。

縱觀大局...爲什麼你想這樣做嗎?

還有,你的評論認爲

我想這個代碼但它會導致訪問衝突與調試版本,因爲_ob_prev和_ob_next沒有設置..

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

被令人擔憂!在轉向更高級的東西之前,您是否成功地定義了一種使用標準內存管理的類型?

+0

refrence counting是正確的,而不是這裏的問題(因此它在發佈版本中工作正常的原因)。問題是,在調試構建下next和prev爲空的事實似乎導致python在清理對象時崩潰,所以看起來我需要一種方法來初始化它們。 – 2009-02-26 07:31:28

0

你可以看看Py_NoneStruct是如何完成的。你的代碼看起來基本正確。

這是一個計數錯誤。靜態分配的對象永遠不會被釋放,所以_Py_ForgetReference不應該被調用。

如果你希望能夠釋放他們,你必須使用使用自定義的分配,而不是靜態初始化。

1

正在做的事情非常可怕。除非這段代碼路徑確實對性能至關重要,否則我建議你像平常一樣在堆上分配對象。