c++ - 在 OpenCV 应用程序中,如何确定内存泄漏的来源并修复它?

标签 c++ memory-leaks opencv

我的 OpenCV 应用程序存在内存泄漏。它是一个中等大小的应用程序,包含许多类和几千行代码。不知何故,我设法在我的应用程序中产生了一个大的内存泄漏,它在几分钟内耗尽了我所有的 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 是答案,我将不胜感激关于如何以更有效的方式使用它的一些提示,因为我对这个工具完全陌生。

最佳答案

不是答案,而是建议:从 OpenCV C 接口(interface)转移到 C++。如果使用得当,无论现在还是将来,它都会将泄漏的可能性降到最低。它嵌入在对象中的智能指针自动释放内存。

在最坏的情况下,您会遇到性能损失(分配/取消分配过多),但这些很容易在分析器中发现。

C++接口(interface)正在使用

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

如果您有一些遗留代码,或者使用其他接口(interface)的第三方,来回转换很容易:

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

其他数据类型(如 CvPoint )会自动转换。 CvSeqstd::vector<T> 取代

关于c++ - 在 OpenCV 应用程序中,如何确定内存泄漏的来源并修复它?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8585852/

相关文章:

c++ - 什么是 "rvalue reference for *this"?

C++ QList 常量正确性

opencv - ARM A9是否支持OpenCL加速?

java - opencv人脸识别,获取图像周围坐标 "bounding box"

opencv - Haar Cascades 与 LBP Cascades 在人脸检测中的对比

c++ - 联盟的内存映射

c++ - 在 Qt C++ 中使用 Dll

iphone - 释放tableview ios iphone中的所有单元格

java - 大型 Hashmap 的 Android 性能问题

.NET - clr.dll 和 native 堆的高内存使用率