在OpenCV应用程序中,如何识别内存泄漏源并进行修复?

时间:2011-12-21 06:25:49

标签: c++ memory-leaks opencv

我的OpenCV应用程序中存在内存泄漏。它是一个中等大小的应用程序,具有类的dozon和几千行代码。不知何故,我设法在我的应用程序中产生了大量的内存泄漏,它在几分钟内就耗尽了我所有的8GB内存。我在使用CMake的Ubuntu 11.10上使用OpenCV C ++ 2.3。

An snapshot of how much memory is freed right after I terminate the app. I can watch the used memory go up to 4gig in a matter of a few minutes

这是一个手动跟踪应用程序,它以每帧15fps的帧速率同时处理两个视频流。

我尝试使用valgrind,如下所示,但valgrind的输出是如此巨大,以至于超出了文本shell可以保留在缓冲区中的数量。我知道我可以将输出保存到日志文件中,但我希望避免阅读所有内容的艰巨任务。这是我使用的valgrind命令:

valgrind --tool=memcheck --leak-check=full --show-reachable=yes ./Gibbon 

以下是valgrind输出的最后几行:

==3573== 5,415,576 (1,176 direct, 5,414,400 indirect) bytes in 7 blocks are definitely lost in loss record 2,571 of 2,571
==3573==    at 0x4C28F9F: malloc (vg_replace_malloc.c:236)
==3573==    by 0x5B2ACD0: cv::fastMalloc(unsigned long) (in /usr/local/lib/libopencv_core.so.2.3.1)
==3573==    by 0x5A7FA9D: cvCreateImageHeader (in /usr/local/lib/libopencv_core.so.2.3.1)
==3573==    by 0x484538: CameraPGR::convertImageToOpenCV(FlyCapture2::Image*) (CameraPGR.cpp:212)
==3573==    by 0x483F52: CameraPGR::grabImage() (CameraPGR.cpp:134)
==3573==    by 0x473F86: start() (GibbonMain.cpp:368)
==3573==    by 0x4725CC: main (GibbonMain.cpp:108)
==3573== 
==3573== LEAK SUMMARY:
==3573==    definitely lost: 24,432 bytes in 33 blocks
==3573==    indirectly lost: 5,414,640 bytes in 15 blocks
==3573==      possibly lost: 2,314,837 bytes in 1,148 blocks
==3573==    still reachable: 496,811 bytes in 4,037 blocks
==3573==         suppressed: 0 bytes in 0 blocks
==3573== 
==3573== For counts of detected and suppressed errors, rerun with: -v
==3573== Use --track-origins=yes to see where uninitialised values come from
==3573== ERROR SUMMARY: 336 errors from 318 contexts (suppressed: 10 from 8)

有什么更好的方法可以解决这个问题?是否有一些工具能够以简洁的方式向我展示哪些函数调用导致了大部分内存分配?如果valgrind是答案,我会很感激如何以更有效的方式使用它,因为我对这个工具完全不熟悉。

1 个答案:

答案 0 :(得分:5)

不是答案,而是一个建议:从OpenCV C界面转移到C ++。如果使用得当,它将最大限度地减少您现在和将来发生泄漏的可能性。它的智能指针嵌入在对象中自动释放内存。

在最坏的情况下,你会有性能损失(allocs / deallocs太多),但很容易在分析器中发现。

C ++界面正在使用

Mat intead of IplImage, 
Point instead of CvPoint, 
cv::function() instead of cvFunction. 

并且您不必声明指向图像的指针:

Mat src = imread("myfile.jpg");
Mat gray; // note that I do not allocate it. 
// This is done automatically in the next functions
cv::cvtColor(src, gray, CV_BGR2GRAY);
imshow("Gray image", gray);
waitKey();

如果您有一些遗留代码或使用其他界面的第三方,则可以轻松来回转换:

Mat src(width, height, CV_8UC3);
IplImage* legacyImg;
legacyImg = &(IplImage)src;

自动转换其他数据类型(如CvPoint)。 CvSeq替换为std::vector<T>