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
'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
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