#759. memtrack comments, sealed the numpy MatND leak
This commit is contained in:
parent
afd42eed4b
commit
6004687563
@ -14,8 +14,12 @@ static PyObject *opencv_error;
|
|||||||
|
|
||||||
struct memtrack_t {
|
struct memtrack_t {
|
||||||
PyObject_HEAD
|
PyObject_HEAD
|
||||||
|
int owner;
|
||||||
void *ptr;
|
void *ptr;
|
||||||
|
int freeptr;
|
||||||
Py_ssize_t size;
|
Py_ssize_t size;
|
||||||
|
PyObject *backing;
|
||||||
|
CvArr *backingmat;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct iplimage_t {
|
struct iplimage_t {
|
||||||
@ -694,6 +698,7 @@ static void cvmatnd_dealloc(PyObject *self)
|
|||||||
{
|
{
|
||||||
cvmatnd_t *pc = (cvmatnd_t*)self;
|
cvmatnd_t *pc = (cvmatnd_t*)self;
|
||||||
Py_DECREF(pc->data);
|
Py_DECREF(pc->data);
|
||||||
|
cvFree(&pc->a);
|
||||||
PyObject_Del(self);
|
PyObject_Del(self);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -923,11 +928,29 @@ static void cvlineiterator_specials(void)
|
|||||||
|
|
||||||
/* memtrack */
|
/* memtrack */
|
||||||
|
|
||||||
|
/* Motivation for memtrack is when the storage for a Mat is an array or buffer
|
||||||
|
object. By setting 'data' to be a memtrack, can deallocate the storage at
|
||||||
|
object destruction.
|
||||||
|
|
||||||
|
For array objects, 'backing' is the actual storage object. memtrack holds the reference,
|
||||||
|
then DECREF's it at dealloc.
|
||||||
|
|
||||||
|
For MatND's, we need to cvDecRefData() on release, and this is what field 'backingmat' is for.
|
||||||
|
|
||||||
|
If freeptr is true, then a straight cvFree() of ptr happens.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
static void memtrack_dealloc(PyObject *self)
|
static void memtrack_dealloc(PyObject *self)
|
||||||
{
|
{
|
||||||
memtrack_t *pi = (memtrack_t*)self;
|
memtrack_t *pi = (memtrack_t*)self;
|
||||||
// printf("===> memtrack_dealloc %p!\n", pi->ptr);
|
if (pi->backing)
|
||||||
cvFree(&pi->ptr);
|
Py_DECREF(pi->backing);
|
||||||
|
if (pi->backingmat)
|
||||||
|
cvDecRefData(pi->backingmat);
|
||||||
|
if (pi->freeptr)
|
||||||
|
cvFree(&pi->ptr);
|
||||||
PyObject_Del(self);
|
PyObject_Del(self);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2188,7 +2211,11 @@ static PyObject *pythonize_CvMat(cvmat_t *m)
|
|||||||
memtrack_t *o = PyObject_NEW(memtrack_t, &memtrack_Type);
|
memtrack_t *o = PyObject_NEW(memtrack_t, &memtrack_Type);
|
||||||
size_t gap = mat->data.ptr - (uchar*)mat->refcount;
|
size_t gap = mat->data.ptr - (uchar*)mat->refcount;
|
||||||
o->ptr = mat->refcount;
|
o->ptr = mat->refcount;
|
||||||
|
o->owner = __LINE__;
|
||||||
|
o->freeptr = true;
|
||||||
o->size = gap + mat->rows * mat->step;
|
o->size = gap + mat->rows * mat->step;
|
||||||
|
o->backing = NULL;
|
||||||
|
o->backingmat = NULL;
|
||||||
PyObject *data = PyBuffer_FromReadWriteObject((PyObject*)o, (size_t)gap, mat->rows * mat->step);
|
PyObject *data = PyBuffer_FromReadWriteObject((PyObject*)o, (size_t)gap, mat->rows * mat->step);
|
||||||
if (data == NULL)
|
if (data == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -2214,11 +2241,14 @@ static PyObject *pythonize_foreign_CvMat(cvmat_t *m)
|
|||||||
#else
|
#else
|
||||||
memtrack_t *o = PyObject_NEW(memtrack_t, &memtrack_Type);
|
memtrack_t *o = PyObject_NEW(memtrack_t, &memtrack_Type);
|
||||||
o->ptr = mat->data.ptr;
|
o->ptr = mat->data.ptr;
|
||||||
|
o->owner = __LINE__;
|
||||||
|
o->freeptr = false;
|
||||||
o->size = mat->rows * mat->step;
|
o->size = mat->rows * mat->step;
|
||||||
|
o->backing = NULL;
|
||||||
|
o->backingmat = mat;
|
||||||
PyObject *data = PyBuffer_FromReadWriteObject((PyObject*)o, (size_t)0, mat->rows * mat->step);
|
PyObject *data = PyBuffer_FromReadWriteObject((PyObject*)o, (size_t)0, mat->rows * mat->step);
|
||||||
if (data == NULL)
|
if (data == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
Py_INCREF(o); // XXX - hack to prevent free of this foreign memory
|
|
||||||
#endif
|
#endif
|
||||||
m->data = data;
|
m->data = data;
|
||||||
m->offset = 0;
|
m->offset = 0;
|
||||||
@ -2242,7 +2272,11 @@ static PyObject *pythonize_IplImage(iplimage_t *cva)
|
|||||||
memtrack_t *o = PyObject_NEW(memtrack_t, &memtrack_Type);
|
memtrack_t *o = PyObject_NEW(memtrack_t, &memtrack_Type);
|
||||||
assert(ipl->imageDataOrigin == ipl->imageData);
|
assert(ipl->imageDataOrigin == ipl->imageData);
|
||||||
o->ptr = ipl->imageDataOrigin;
|
o->ptr = ipl->imageDataOrigin;
|
||||||
|
o->owner = __LINE__;
|
||||||
|
o->freeptr = true;
|
||||||
o->size = ipl->height * ipl->widthStep;
|
o->size = ipl->height * ipl->widthStep;
|
||||||
|
o->backing = NULL;
|
||||||
|
o->backingmat = NULL;
|
||||||
PyObject *data = PyBuffer_FromReadWriteObject((PyObject*)o, (size_t)0, o->size);
|
PyObject *data = PyBuffer_FromReadWriteObject((PyObject*)o, (size_t)0, o->size);
|
||||||
if (data == NULL)
|
if (data == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -2253,13 +2287,11 @@ static PyObject *pythonize_IplImage(iplimage_t *cva)
|
|||||||
return (PyObject*)cva;
|
return (PyObject*)cva;
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyObject *pythonize_CvMatND(cvmatnd_t *m)
|
static PyObject *pythonize_CvMatND(cvmatnd_t *m, PyObject *backing = NULL)
|
||||||
{
|
{
|
||||||
//
|
//
|
||||||
// Need to make this CvMatND look like any other, with a Python
|
// Need to make this CvMatND look like any other, with a Python
|
||||||
// string as its data.
|
// buffer object as its data.
|
||||||
// So copy the image data into a Python string object, then release
|
|
||||||
// it.
|
|
||||||
//
|
//
|
||||||
|
|
||||||
CvMatND *mat = m->a;
|
CvMatND *mat = m->a;
|
||||||
@ -2268,15 +2300,20 @@ static PyObject *pythonize_CvMatND(cvmatnd_t *m)
|
|||||||
PyObject *data = PyString_FromStringAndSize((char*)(mat->data.ptr), mat->dim[0].size * mat->dim[0].step);
|
PyObject *data = PyString_FromStringAndSize((char*)(mat->data.ptr), mat->dim[0].size * mat->dim[0].step);
|
||||||
#else
|
#else
|
||||||
memtrack_t *o = PyObject_NEW(memtrack_t, &memtrack_Type);
|
memtrack_t *o = PyObject_NEW(memtrack_t, &memtrack_Type);
|
||||||
o->ptr = cvPtr1D(mat, 0);
|
o->ptr = mat->data.ptr;
|
||||||
|
o->owner = __LINE__;
|
||||||
|
o->freeptr = false;
|
||||||
o->size = cvmatnd_size(mat);
|
o->size = cvmatnd_size(mat);
|
||||||
|
Py_XINCREF(backing);
|
||||||
|
o->backing = backing;
|
||||||
|
o->backingmat = mat;
|
||||||
PyObject *data = PyBuffer_FromReadWriteObject((PyObject*)o, (size_t)0, o->size);
|
PyObject *data = PyBuffer_FromReadWriteObject((PyObject*)o, (size_t)0, o->size);
|
||||||
|
Py_DECREF(o); // Now 'data' holds the only reference to 'o'
|
||||||
if (data == NULL)
|
if (data == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
#endif
|
#endif
|
||||||
m->data = data;
|
m->data = data;
|
||||||
m->offset = 0;
|
m->offset = 0;
|
||||||
// cvDecRefData(mat); // Ref count should be zero here, so this is a release
|
|
||||||
|
|
||||||
return (PyObject*)m;
|
return (PyObject*)m;
|
||||||
}
|
}
|
||||||
@ -2787,6 +2824,8 @@ static PyObject *pycvfromarray(PyObject *self, PyObject *args, PyObject *kw)
|
|||||||
static PyObject *fromarray(PyObject *o, int allowND)
|
static PyObject *fromarray(PyObject *o, int allowND)
|
||||||
{
|
{
|
||||||
PyObject *ao = PyObject_GetAttrString(o, "__array_struct__");
|
PyObject *ao = PyObject_GetAttrString(o, "__array_struct__");
|
||||||
|
PyObject *retval;
|
||||||
|
|
||||||
if ((ao == NULL) || !PyCObject_Check(ao)) {
|
if ((ao == NULL) || !PyCObject_Check(ao)) {
|
||||||
PyErr_SetString(PyExc_TypeError, "object does not have array interface");
|
PyErr_SetString(PyExc_TypeError, "object does not have array interface");
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -2847,7 +2886,7 @@ static PyObject *fromarray(PyObject *o, int allowND)
|
|||||||
return (PyObject*)failmsg("cv.fromarray array can be 2D or 3D only, see allowND argument");
|
return (PyObject*)failmsg("cv.fromarray array can be 2D or 3D only, see allowND argument");
|
||||||
}
|
}
|
||||||
m->a->data.ptr = (uchar*)pai->data;
|
m->a->data.ptr = (uchar*)pai->data;
|
||||||
return pythonize_foreign_CvMat(m);
|
retval = pythonize_foreign_CvMat(m);
|
||||||
} else {
|
} else {
|
||||||
int dims[CV_MAX_DIM];
|
int dims[CV_MAX_DIM];
|
||||||
int i;
|
int i;
|
||||||
@ -2856,8 +2895,11 @@ static PyObject *fromarray(PyObject *o, int allowND)
|
|||||||
cvmatnd_t *m = PyObject_NEW(cvmatnd_t, &cvmatnd_Type);
|
cvmatnd_t *m = PyObject_NEW(cvmatnd_t, &cvmatnd_Type);
|
||||||
ERRWRAP(m->a = cvCreateMatND(pai->nd, dims, type));
|
ERRWRAP(m->a = cvCreateMatND(pai->nd, dims, type));
|
||||||
m->a->data.ptr = (uchar*)pai->data;
|
m->a->data.ptr = (uchar*)pai->data;
|
||||||
return pythonize_CvMatND(m);
|
|
||||||
|
retval = pythonize_CvMatND(m, ao);
|
||||||
}
|
}
|
||||||
|
Py_DECREF(ao);
|
||||||
|
return retval;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user