简体   繁体   English

cvCreateMat内存泄漏(OpenCV)

[英]cvCreateMat memory leak (OpenCV)

Alright; 好的; so I'm finding an odd memory leak when attempting to use cvCreateMat to make room for my soon-to-be-filled mat. 因此,在尝试使用cvCreateMat为即将填充的垫子腾出空间时,我发现了奇怪的内存泄漏。 Below is what I am attempting to do; 以下是我正在尝试做的事情; adaptiveThreshold didn't like it when I put the 3-channel image in, so I wanted to split it into its separate channels. 当我放入3通道图像时,adaptiveThreshold不喜欢它,因此我想将其拆分为单独的通道。 It works! 有用! But every time we go through this particular function we gain another ~3MB of memory. 但是,每当我们执行此特定功能时,我们都会获得大约3MB的内存。 Since this function is expected to run a few hundred times, this becomes a rather noticeable problem. 由于该功能有望运行数百次,因此这成为一个相当明显的问题。

So here's the code: 所以这是代码:

void adaptiveColorThreshold(Mat *inputShot, int adaptiveMethod, int blockSize, int cSubtraction)
{
    Mat newInputShot = (*inputShot).clone();
    Mat inputBlue = cvCreateMat(newInputShot.rows, newInputShot.cols, CV_8UC1);
    Mat inputGreen = cvCreateMat(newInputShot.rows, newInputShot.cols, CV_8UC1);
    Mat inputRed = cvCreateMat(newInputShot.rows, newInputShot.cols, CV_8UC1);

    for(int rows = 0; rows < newInputShot.rows; rows++)
    {
        for(int cols = 0; cols < newInputShot.cols; cols++)
        {
            inputBlue.data[inputBlue.step[0]*rows + inputBlue.step[1]*cols] = newInputShot.data[newInputShot.step[0]*rows + newInputShot.step[1]*cols + 0];
            inputGreen.data[inputGreen.step[0]*rows + inputGreen.step[1]*cols] = newInputShot.data[newInputShot.step[0]*rows + newInputShot.step[1]*cols + 1];
            inputRed.data[inputRed.step[0]*rows + inputRed.step[1]*cols] = newInputShot.data[newInputShot.step[0]*rows + newInputShot.step[1]*cols + 2];
        }
    }

    adaptiveThreshold(inputBlue, inputBlue, 255, adaptiveMethod, THRESH_BINARY, blockSize, cSubtraction);
    adaptiveThreshold(inputGreen, inputGreen, 255, adaptiveMethod, THRESH_BINARY, blockSize, cSubtraction);
    adaptiveThreshold(inputRed, inputRed, 255, adaptiveMethod, THRESH_BINARY, blockSize, cSubtraction);

    for(int rows = 0; rows < (*inputShot).rows; rows++)
    {
        for(int cols = 0; cols < (*inputShot).cols; cols++)
        {
            (*inputShot).data[(*inputShot).step[0]*rows + (*inputShot).step[1]*cols + 0] = inputBlue.data[inputBlue.step[0]*rows + inputBlue.step[1]*cols];
            (*inputShot).data[(*inputShot).step[0]*rows + (*inputShot).step[1]*cols + 1] = inputGreen.data[inputGreen.step[0]*rows + inputGreen.step[1]*cols];
            (*inputShot).data[(*inputShot).step[0]*rows + (*inputShot).step[1]*cols + 2] = inputRed.data[inputRed.step[0]*rows + inputRed.step[1]*cols];
        }
    }

    inputBlue.release();
    inputGreen.release();
    inputRed.release();
    newInputShot.release();

    return;
}

So going through it one line at a time... 所以一次要一行...

  • newInputShot adds ~3MB newInputShot增加了〜3MB
  • inputBlue adds ~1MB inputBlue添加〜1MB
  • inputGreen adds ~1MB inputGreen增加〜1MB
  • and inputRed adds ~1MB 然后输入红色加〜1MB

So far, so good - need memory to hold the data. 到目前为止,一切都很好-需要内存来保存数据。 newInputShot gets its data right off the bat, but inputRGB need to get their data from newInputShot - so we just allocate the space to be filled in the upcoming for-loop, which (as expected) allocates no new memory, just fills in the space already claimed. newInputShot可以立即获取其数据,但是inputRGB需要从newInputShot中获取其数据-因此,我们只是在即将到来的for循环中分配要填充的空间,(如预期的那样)不分配任何新内存,仅填充空间已经声称。

The adaptiveThresholds don't add any new memory either, since they're simply supposed to overwrite what is already there, and the next for-loop writes straight to inputShot; adaptiveThresholds也不添加任何新的内存,因为它们只是要覆盖已经存在的内容,而下一个for循环将直接写入inputShot。 no new memory needed there. 那里不需要新的内存。 So now we get around to (manually) releasing the memory. 因此,现在我们开始(手动)释放内存。

  • Releasing inputBlue frees up 0MB 释放输入蓝色释放0MB
  • Releasing inputGreen frees up 0MB 释放输入绿色释放0MB
  • Releasing inputRed frees up 0MB 释放输入红色释放0MB
  • Releasing newInputShot frees up ~3MB 释放newInputShot可释放约3MB

Now, according to the OpenCV documentation site: " OpenCV handles all the memory automatically. " 现在,根据OpenCV文档站点:“ OpenCV自动处理所有内存。

First of all, std::vector, Mat, and other data structures used by the functions and methods have destructors that deallocate the underlying memory buffers when needed. 首先,函数和方法使用的std :: vector,Mat和其他数据结构具有析构函数,这些析构函数可以在需要时释放基础内存缓冲区。 This means that the destructors do not always deallocate the buffers as in case of Mat. 这意味着析构函数并不总是像Mat一样总是释放缓冲区。 They take into account possible data sharing. 它们考虑了可能的数据共享。 A destructor decrements the reference counter associated with the matrix data buffer. 析构函数递减与矩阵数据缓冲区关联的参考计数器。 The buffer is deallocated if and only if the reference counter reaches zero, that is, when no other structures refer to the same buffer. 当且仅当参考计数器达到零时,即没有其他结构引用同一缓冲区时,才释放缓冲区。 Similarly, when a Mat instance is copied, no actual data is really copied. 类似地,当复制Mat实例时,不会真正复制任何实际数据。 Instead, the reference counter is incremented to memorize that there is another owner of the same data. 取而代之的是,增加参考计数器以记住相同数据的另一个所有者。 There is also the Mat::clone method that creates a full copy of the matrix data. 还有Mat :: clone方法可创建矩阵数据的完整副本。

TLDR the quote: Related mats get clumped together in a super-mat that gets released all at once when nothing is left using it. TLDR的报价是:相关的垫子聚集在一个超级垫子中,当不使用任何东西时,这些垫子会立即全部释放。

This is why I created newInputShot as a clone (that doesn't get clumped with inputShot) - so I could see if this was occurring with the inputRGBs. 这就是为什么我将newInputShot创建为一个克隆(它不会与inputShot捆绑在一起)的原因-因此我可以查看输入RGB是否正在发生这种情况。 Well... nope! 好吧,不! the inputRGBs are their own beast that refuse to be deallocated. inputRGB是它们自己的拒绝释放的野兽。 I know it isn't any of the intermediate functions because this snippet does the exact same thing: 我知道它不是任何中间函数,因为此代码段执行的功能完全相同:

void adaptiveColorThreshold(Mat *inputShot, int adaptiveMethod, int blockSize, int cSubtraction)
{
    Mat newInputShot = (*inputShot).clone();
    Mat inputBlue = cvCreateMat(newInputShot.rows, newInputShot.cols, CV_8UC1);
    Mat inputGreen = cvCreateMat(newInputShot.rows, newInputShot.cols, CV_8UC1);
    Mat inputRed = cvCreateMat(newInputShot.rows, newInputShot.cols, CV_8UC1);

    inputBlue.release();
    inputGreen.release();
    inputRed.release();
    newInputShot.release();

    return;
}

That's about as simple as it gets. 那差不多就变得简单了。 Allocate - fail to Deallocate. 分配-无法取消分配。 So what's going on with cvCreateMat? 那么cvCreateMat是怎么回事?

I would suggest not to use cvCreateMat and you don't need to clone the original Mat either. 我建议不要使用cvCreateMat,也不需要克隆原始Mat。 Look into using split() and merge() functions. 研究使用split()merge()函数。 They will do the dirty work for you and will return Mat's that will handle memory for you. 他们将为您完成肮脏的工作,并返回Mat来为您处理内存。 I don't have OpenCV installed right now so i can't test any of the code but i'm sure that's the route you want to take. 我现在没有安装OpenCV,因此我无法测试任何代码,但我确定这就是您要采用的方法。

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

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