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

Ara*_*ras 5 c++ opencv memory-leaks

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

我终止应用程序后立即释放了多少内存的快照. 我可以在几分钟内看到用过的内存高达4gig

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

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

valgrind --tool=memcheck --leak-check=full --show-reachable=yes ./Gibbon 
Run Code Online (Sandbox Code Playgroud)

这是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)
Run Code Online (Sandbox Code Playgroud)

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

Sam*_*Sam 5

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

在最坏的情况下,您将受到性能损失(过多的allocs/deallocs),但这些很容易在分析器中发现.

C++接口正在使用

Mat intead of IplImage, 
Point instead of CvPoint, 
cv::function() instead of cvFunction. 
Run Code Online (Sandbox Code Playgroud)

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

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();
Run Code Online (Sandbox Code Playgroud)

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

Mat src(width, height, CV_8UC3);
IplImage* legacyImg;
legacyImg = &(IplImage)src;
Run Code Online (Sandbox Code Playgroud)

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