2011-08-08 10 views
7

Cada vez que llamé a mi función, el uso de la memoria aumenta alrededor de + 10M por llamada, así que creo que hay alguna pérdida de memoria aquí.¿Dónde debería poner Py_INCREF y Py_DECREF en este bloque en la extensión Python C?

.... 
PyObject *pair = PyTuple_New(2), *item = PyList_New(0); 

PyTuple_SetItem(pair, 0, PyInt_FromLong(v[j])); 

if(v[j] != DISTANCE_MAX && (p[j] || d[0][j])){ 
    jp=j; 
    while(jp!=istart) { 
    PyList_Append(item, PyInt_FromLong(jp)); 
    jp=p[jp]; 
    } 

    PyList_Append(item, PyInt_FromLong(jp)); 

    PyList_Reverse(item); 
} 

PyTuple_SetItem(pair, 1, item); 

return pair; 
.... 

cuando leí document, algunas llamadas como

void 
bug(PyObject *list) 
{ 
    PyObject *item = PyList_GetItem(list, 0); 

    PyList_SetItem(list, 1, PyInt_FromLong(0L)); 
    PyObject_Print(item, stdout, 0); /* BUG! */ 
} 

necesidad de poner los contadores de referencia como éste

void 
no_bug(PyObject *list) 
{ 
    PyObject *item = PyList_GetItem(list, 0); 

    Py_INCREF(item); 
    PyList_SetItem(list, 1, PyInt_FromLong(0L)); 
    PyObject_Print(item, stdout, 0); 
    Py_DECREF(item); 
} 

Así que, ¿Dónde debo poner Py_INCREF y Py_DECREF en mi función?

Respuesta

10

Los objetos que se crean con PyInt_FromLong() y lo agrega a la lista debe mantenerse en una variable local.

La razón es ownership rules: PyInt_FromLong() genera una referencia que usted posee. En la llamada a PyTuple_SetItem(), pierde esta propiedad nuevamente, porque PyTuple_SetItem() se la "roba", por lo que no tiene que preocuparse. Pero PyList_Append() no lo hace, aumenta el recuento. Para que GC tenga el objeto correctamente, debe liberar su propiedad DECREF'ing.

Así, en lugar de PyList_Append (artículo, PyInt_FromLong (JP)), hacer lo siguiente:

PyObject * jpo = PyInt_FromLong(jp); 
// do some error checking here 
PyList_Append(item, jpo); 
Py_DECREF(jpo); 

Esto hará que el programa haga lo correcto.

0

Cuando se crea un objeto, su refcount será 1, así que después de esto:

my_item = PyInt_FromLong(jp) 

el objeto en my_item tendrá un refcount de 1.

Al almacenar un elemento en un contenedor , contador de referencia del artículo se incrementa de modo que será retenido el artículo, así que después de esto:

PyList_Append(my_list, my_item); 

el objeto en my_item tendrá un refcou nt de 2.

Por lo tanto, esta línea:

PyList_Append(item, PyInt_FromLong(jp)); 

creará un objeto con refcount 1 y almacenarlo en la lista, incrementando refcount del objeto a 2.

+8

Entonces ... ¿dónde debería poner 'Py_INCREF' y' Py_DECREF'? No respondiste su pregunta. – agf

Cuestiones relacionadas