2010-11-14 39 views
7

Je demande ici parce que je n'ai reçu aucune aide des développeurs OpenCV jusqu'à présent. J'ai réduit le problème à un cas de test très simple, donc probablement quelqu'un avec un peu d'expérience avec CPython pourrait aider ici.OpenCV: fuite de mémoire avec l'interface Python mais pas dans la version C

Ce code C ne fuit pas:

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

Ce code Python ne fuit:

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

J'ai cherché dans le code CPython (de OpenCVS code de tronc actuel SVN) et trouvé ceci:

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

Et des en-têtes 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; 

Je ne comprends pas exactement tout parce que je ne ai jamais travaillé avec le C-interface Python avant. Mais probablement le bug que je recherche est quelque part dans ce code.

Ai-je raison? Ou où devrais-je rechercher le bug? Comment pourrais-je le réparer?

(Note pour les personnes ayant vu une version antérieure de cette question: J'ai regardé le mauvais code, leur interface SWIG était obsolète et n'était plus utilisée (mais le code était toujours présent dans SVN, c'est pourquoi je l'ai confondu . donc, ne pas regarder dans interfaces/swig, ce code est vieux et pas utilisé. Le code actuel vit à modules/python.)


Upstream bug report: memleak in OpenCV Python CreateHist

Répondre

2

Il a été corrigé.

changé il y a 3 semaines par jamesb

  • a changé son statut de accepté de fermer
  • résolution réglée sur fixe

fixe dans r4526

Les paramètres gammes n'étaient pas libéré, et l'itérateur sur les plages n'a pas été DECREF'ed. Les régressions passent maintenant et la boucle d'origine ne fuit pas.

0

Je pense que vous avez problème de la collecte des ordures dans la mesure où vous ne laissez jamais la boucle

Est-ce que cela fonctionne plus comme prévu?

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

'CreateHist' renvoie un objet. Parce qu'il n'est assigné à aucune variable, il devrait être libéré à un moment donné dans le futur (il devrait entrer directement dans le GC).Comme Python lui-même fait ce droit, OpenCV doit avoir gardé une autre référence à quelque chose. – Albert

+0

De plus, 'cv = None' n'est pas vraiment lié au problème lui-même. 'cv' est un module ici et il est libéré correctement à la fermeture de Python. – Albert