2017-10-16 86 views
1

我一直在努力研究Python C/C++擴展,除了一個方法添加了兩個名爲「int_obj」的結構,並且返回一個新的結構稱爲「add_int_obj」。Python擴展方法的分段錯誤

到目前爲止,該擴展只有兩種方法,「價值」完美地工作,「添加」,這是有問題的方法。

我用下面的test.py腳本測試它:

import intobj 
val1 = intobj.IntObj(3) 
val2 = intobj.IntObj(5) 
print "Val1" 
print val1 
print "Val1 Value" 
print val1.value() 
print "Val2" 
print val2 
print "Val2 Value" 
print val2.value() 
val3 = intobj.add(val1, val2) 
print "Val3" 
print val3 
print "Val3 Value" 
print val3.value() 

當我執行我得到下面的輸出:

$ python test.py 
Val1 
<intobj.IntObj object at 0x7faf3fc8a0f0> 
Val1 Value 
3 
Val2 
<intobj.IntObj object at 0x7faf3fc8a108> 
Val2 Value 
5 
IntObj_add start 
Int Obj Value A: 3 
Int Obj Value B: 5 
Int Obj Value Result: 8 
IntObj_add end 
Val3 
Segmentation fault (core dumped) 

擴展方法來處理增加的兩種結構是:

static PyObject *IntObj_add(PyObject *self,PyObject *args) 
{ 
    std::cout<<"IntObj_add start"<<std::endl; 

    PyObject *a,*b; 

    IntObj *result; 

    if (!PyArg_ParseTuple(args, "OO", &a, &b)) 
      return NULL; 

    std::cout<<"Int Obj Value A: "<<int_obj_value(((IntObj*)a)->content)<<std::endl; 
    std::cout<<"Int Obj Value B: "<<int_obj_value(((IntObj*)b)->content)<<std::endl; 

    result = new IntObj; 

    Py_INCREF(result); 

    result->content = add_int_obj(((IntObj*)a)->content,((IntObj*)b)->content); 

    std::cout<<"Int Obj Value Result: "<<int_obj_value(result->content)<<std::endl; 

    std::cout<<"IntObj_add end"<<std::endl; 

    return (PyObject*)result; 
} 

由於分段錯誤只出現在方法外,當我嘗試打印該對象,而不是當我嘗試獲取值時,我的猜測是垃圾收集器正在刪除方法試圖返回的PyObject。

如何安全地返回結果對象?

+0

'new'是創建Python對象的一種相當可疑的方式。 – user2357112

+0

@ user2357112你會建議該對象應該創建不同嗎?如果結構在方法內部工作,爲什麼會出現這種問題? –

+0

如果通過「在方法內部工作」,您的意思是「不會崩潰*然後*」,那麼肯定,但C++不會承諾在您做錯事情時立即崩潰。 'result'中有重要的東西沒有被初始化,比如refcount和類型指針。 – user2357112

回答

0

感謝@ user2357112的評論和一些閱讀刷新我的C/C++我記得我可以用它之前定義的方法,這樣我可以解決我的問題的方式如下:

我在定義我的方法開始像這樣的文件:

static PyObject *IntObj_add(PyObject *, PyObject *); 

然後是PyTypeObject實現我實現的方法創建調用該類型對象的對象,而不是新的後如下:

static PyObject *IntObj_add(PyObject *self, PyObject *args) 
{ 
    PyObject *a, *b; 

    IntObj *result; 

    if (!PyArg_ParseTuple(args, "OO", &a, &b)) 
     return NULL; 

    result = (IntObj *)IntObjType.tp_alloc(&IntObjType, 0); 

    result->content = add_int_obj(((IntObj *)a)->content, ((IntObj *)b)->content); 

    return (PyObject *)result; 
}