2012-06-02 2 views
1

Я потерял Py_DECREF/INCREF при обработке PyList_Append. Кто-нибудь может комментировать следующие коды?потеряно на Py_DECREF/INCREF при обработке PyList_Append в расширении Python C

PyObject * bugmaybe(PyObject *self, PyObject *args) 
{ 
    PyObject * trio=PyList_New(0); 
    PyObject * trio_tmp; 
    PyObject * otmp = PyFloat_FromDouble(1.2); 
    PyList_Append(trio_tmp,otmp); 
    //Py_DECREF(otmp); 
    otmp = PyFloat_FromDouble(2.3); 
    PyList_Append(trio_tmp,otmp); 
    //Py_DECREF(otmp); 
    PyList_Append(trio,trio_tmp); 
    Py_INCREF(trio_tmp); 
} 

ответ

4

Если вы знаете размер списка вверх, его обычно быстрее, чтобы создать список с нужным размером и использовать PyList_SetItem().

Ваш код просто неверный, trio_tmp неинициализирован.

Попробуйте это:

PyObject * bugmaybe(PyObject *self, PyObject *args) 
{ 
    PyObject * trio=PyList_New(3); 
    PyObject * otmp = PyFloat_FromDouble(1.2); 
    PyList_SetItem(trio,0,otmp); 
    otmp = PyFloat_FromDouble(2.3); 
    PyList_SetItem(trio,1,otmp); 
    PyList_Append(trio,2, PyList_New(0)); 
    return trio; 
} 

Если вы действительно хотите использовать PyList_Append, код в основном нормально, просто не хватает инициализации для trio_tmp и лишние Py_INCREF в конце.

PyObject * bugmaybe(PyObject *self, PyObject *args) 
{ 
    PyObject * trio=PyList_New(0); 
    // trio has refcount 1 
    PyObject * trio_tmp = PyList_New(0); 
    // trio_tmp has recount 1 
    PyObject * otmp = PyFloat_FromDouble(1.2); 
    // otmp has recount 1 
    PyList_Append(trio_tmp,otmp); 
    // Append does not steal a reference, so otmp refcoun = 2 
    Py_DECREF(otmp); 
    // otmp refcount = 1, but stored in the list so the pointer var 
    // can be reused 
    otmp = PyFloat_FromDouble(2.3); 
    PyList_Append(trio_tmp,otmp); 
    Py_DECREF(otmp); 
    // as above 
    PyList_Append(trio,trio_tmp); 
    // decrement refcount for trio_tmp, as it has recount 2 now. 
    Py_DECREF(trio_tmp); 
    return trio; 
} 

Код выше будет эквивалентен:

trio = [] 
trio_tmp = [] 
otmp = 1.2 
trio_tmp.append(otmp) 
otmp = 2.3 
trio_tmp.append(otmp) 
trio.append(trio_tmp) 

Надеется, что это помогает. Главный намек в документах, если он говорит: «Похищает ссылку», тогда функция в основном берет на себя ответственность, если она говорит «Новая ссылка», тогда она сделала для вас INCREF, если ничего не сказано, вероятно, что пара INCREF и DECREF по мере необходимости.

+0

Я работаю круто! Большое спасибо! –

1

PyList_Append() не «украсть» ссылку, поэтому, если вы не собираетесь использовать прилагаемую значение после decref него.

Кроме того, не забудьте вернуть PyObject* из этой функции или система будет считать, что произошло исключение.

+0

Фактически, «трио» было передано путем ссылки на это расширение C. Однако после этого функция вызова python рухнула. Не могу понять, почему. –