2010-11-14 6 views
7

Pregunto aquí porque hasta ahora no he recibido ayuda de los desarrolladores de OpenCV. Reduje el problema a un caso de prueba muy simple así que probablemente cualquier persona con experiencia en CPython podría ayudar aquí.OpenCV: pérdida de memoria con la interfaz de Python pero no en la versión C

Este código C no se escapa:

int main() { 
    while(true) { 
     int hist_size[] = {40}; 
     float range[] = {0.0f,255.0f}; 
     float* ranges[] = {range}; 
     CvHistogram* hist = cvCreateHist(1, hist_size, CV_HIST_ARRAY, ranges, 1); 
     cvReleaseHist(&hist); 
    } 
} 

Este código Python hace de fugas:

while True: cv.CreateHist([40], cv.CV_HIST_ARRAY, [[0,255]], 1) 

he buscado en el código CPython (de OpenCVs vigente código tronco SVN) y encontramos este:

struct cvhistogram_t { 
    PyObject_HEAD 
    CvHistogram h; 
    PyObject *bins; 
}; 

...

/* cvhistogram */ 

static void cvhistogram_dealloc(PyObject *self) 
{ 
    cvhistogram_t *cvh = (cvhistogram_t*)self; 
    Py_DECREF(cvh->bins); 
    PyObject_Del(self); 
} 

static PyTypeObject cvhistogram_Type = { 
    PyObject_HEAD_INIT(&PyType_Type) 
    0,          /*size*/ 
    MODULESTR".cvhistogram",    /*name*/ 
    sizeof(cvhistogram_t),     /*basicsize*/ 
}; 

static PyObject *cvhistogram_getbins(cvhistogram_t *cvh) 
{ 
    Py_INCREF(cvh->bins); 
    return cvh->bins; 
} 

static PyGetSetDef cvhistogram_getseters[] = { 
    {(char*)"bins", (getter)cvhistogram_getbins, (setter)NULL, (char*)"bins", NULL}, 
    {NULL} /* Sentinel */ 
}; 

static void cvhistogram_specials(void) 
{ 
    cvhistogram_Type.tp_dealloc = cvhistogram_dealloc; 
    cvhistogram_Type.tp_getset = cvhistogram_getseters; 
} 

...

static PyObject *pycvCreateHist(PyObject *self, PyObject *args, PyObject *kw) 
{ 
    const char *keywords[] = { "dims", "type", "ranges", "uniform", NULL }; 
    PyObject *dims; 
    int type; 
    float **ranges = NULL; 
    int uniform = 1; 

    if (!PyArg_ParseTupleAndKeywords(args, kw, "Oi|O&i", (char**)keywords, &dims, &type, convert_to_floatPTRPTR, (void*)&ranges, &uniform)) { 
    return NULL; 
    } 
    cvhistogram_t *h = PyObject_NEW(cvhistogram_t, &cvhistogram_Type); 
    args = Py_BuildValue("Oi", dims, CV_32FC1); 
    h->bins = pycvCreateMatND(self, args); 
    Py_DECREF(args); 
    if (h->bins == NULL) { 
    return NULL; 
    } 
    h->h.type = CV_HIST_MAGIC_VAL; 
    if (!convert_to_CvArr(h->bins, &(h->h.bins), "bins")) 
    return NULL; 

    ERRWRAP(cvSetHistBinRanges(&(h->h), ranges, uniform)); 

    return (PyObject*)h; 
} 

Y a partir de las cabeceras OpenCV C:

typedef struct CvHistogram 
{ 
    int  type; 
    CvArr* bins; 
    float thresh[CV_MAX_DIM][2]; /* For uniform histograms.      */ 
    float** thresh2;    /* For non-uniform histograms.     */ 
    CvMatND mat;     /* Embedded matrix header for array histograms. */ 
} 
CvHistogram; 

No entiendo exactamente todo porque nunca he trabajado con la C-interfaz para Python antes. Pero probablemente el error que estoy buscando se encuentra en algún lugar de este código.

¿Estoy en lo cierto? ¿O dónde debería buscar el error? ¿Cómo lo arreglaría?

(Nota para las personas que han visto una versión anterior de esta pregunta: miré el código incorrecto. Su interfaz SWIG estaba obsoleta y no se usaba más (pero el código todavía estaba en SVN, es por eso que lo confundí) . Así que no mire al interfaces/swig, este código es viejo y no se utiliza. El código actual vive en modules/python.)


Upstream bug report: memleak in OpenCV Python CreateHist

Respuesta

2

Ha sido corregido.

cambió hace 3 semanas por jamesb

  • estado cambiado de aceptado cerrado resolución
  • configurado como fijo

fija en r4526

Los parámetros de rangos no se estaban liberado, y el iterador sobre los rangos no estaba siendo REDUCIDO. Las regresiones ahora pasan, y el bucle original no tiene fugas.

0

yo creo que hay problema de recolección de basura, en la que nunca deja el bucle.

¿Funciona más de lo esperado?

while True: 
    cv.CreateHist([40], cv.CV_HIST_ARRAY, [[0,255]], 1) 
    cv = None 
+0

'CreateHist' devuelve un objeto. Debido a que no está asignado a ninguna variable, debería liberarse en algún momento en el futuro (debe entrar directamente en el GC).Como Python mismo hace ese derecho, OpenCV debe haber guardado otra referencia a algo. – Albert

+0

Además, 'cv = None' no está realmente relacionado con el problema en sí. 'cv' es un módulo aquí y se libera correctamente al salir de Python. – Albert

Cuestiones relacionadas