简体   繁体   English

OpenCV:Python界面的内存泄漏,但C版本没有

[英]OpenCV: memory leak with Python interface but not in the C version

I am asking here because I haven't gotten any help from the OpenCV developers so far. 我在这里问,因为到目前为止我还没有得到OpenCV开发人员的任何帮助。 I reduced the problem to a very simple test case so probably anyone with some background with CPython could help here. 我把问题简化为一个非常简单的测试用例,所以可能任何有CPython背景的人都可以在这里提供帮助。

This C code does not leak: 这个C代码不泄漏:

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

This Python code does leak: 这个Python代码确实泄漏:

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

I searched through the CPython code (of OpenCVs current SVN trunk code) and found this: 我搜索了CPython代码(OpenCVs当前的SVN中继代码),发现了这个:

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

And from the OpenCV C headers: 从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;

I don't exactly understand everything because I never worked with the C-interface to Python before. 我并不完全理解所有内容,因为我之前从未使用过C接口。 But probably the bug I am searching for is somewhere in this code. 但是我正在搜索的错误可能就是这段代码中的某个地方。

Am I right? 我对吗? Or where should I search for the bug? 或者我应该在哪里搜索错误? How would I fix it? 我该如何解决?

(Note for people who have seen an earlier version of this question: I looked at the wrong code. Their SWIG interface was deprecated and not used anymore (but the code was still there in SVN, this is why I confused it. So don't look into interfaces/swig , this code is old and not used. The current code lives in modules/python .) (注意那些看过这个问题的早期版本的人:我查看了错误的代码。他们的SWIG界面已被弃用,不再使用了(但代码仍然存在于SVN中,这就是为什么我感到困惑。所以不要看看interfaces/swig ,这段代码很旧而且没用过。当前的代码存在于modules/python 。)


Upstream bug report: memleak in OpenCV Python CreateHist 上游错误报告:OpenCV Python CreateHist中的memleak

It has been fixed. 它已被修复。

Changed 3 weeks ago by jamesb 由jamesb在3周前更改

  • status changed from accepted to closed 状态从接受变为关闭
  • resolution set to fixed 分辨率设置为固定

Fixed in r4526 已在r4526修复

The ranges parameters were not being freed, and the iterator over ranges was not being DECREF'ed. 范围参数未被释放,并且范围内的迭代器未被DECREF处理。 Regressions now pass, and original loop does not leak. 回归现在通过,原始循环不会泄漏。

I think you have garbage collection issue, in that you never leave the loop. 我认为你有垃圾收集问题,因为你永远不会离开循环。

Does this work more as expected? 这是否更符合预期?

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM