解决MFC使用OpenCV动态库会误报内存泄露的问题(太多人遇到这个问题了)

简介: 解决MFC使用OpenCV动态库会误报内存泄露的问题(太多人遇到这个问题了)

本人最近做项目,发现在MFC Debug环境,使用OpenCV动态库会误报内存泄露。使用windbg.exe工具仍然无法排查问题所在。于是在opencv开源站点提交了issues。链接如下:


https://github.com/opencv/opencv/issues/16591


另外,Opencv论坛也有人提这个问题,但是似乎没有太好的办法:


http://www.opencv.org.cn/forum/forum.php?mod=viewthread&tid=265559 中文论坛


https://answers.opencv.org/questions/scope:all/sort:activity-desc/page:1/query:mfc%20memory%20leak/ 英文论坛


https://groups.google.com/forum/#!topic/microsoft.public.vc.mfc/5tMGENar9R4/discussion



1、问题描述


新建一个MFC应用程序,导入OpenCV动态库,程序使用了opencv变量和函数。当程序在运行时,一切正常,但是点击应用程序关闭按钮时,那么问题就来了,输出窗口会出现一大堆内存泄漏问题。如下所示:


Detected memory leaks!
Dumping objects ->
{468} normal block at 0x0051D9B8, 8 bytes long.
 Data: <        > E4 DA C8 00 00 00 00 00 
{467} normal block at 0x0051D980, 8 bytes long.
 Data: <8       > 38 DB C8 00 00 00 00 00 
{466} normal block at 0x0051D948, 8 bytes long.
 Data: <        > 00 DB C8 00 00 00 00 00 
{465} normal block at 0x0051D910, 8 bytes long.
 Data: <        > 1C DB C8 00 00 00 00 00 
{464} normal block at 0x0051D8D8, 8 bytes long.
 Data: <$       > 24 A7 C1 00 00 00 00 00 
{463} normal block at 0x0051D8A0, 8 bytes long.
 Data: <x       > 78 A7 C1 00 00 00 00 00 
......
{178} normal block at 0x00514C28, 8 bytes long.
 Data: < V      > AC 56 A5 10 00 00 00 00 
{177} normal block at 0x00514BF0, 8 bytes long.
 Data: < V      > 9C 56 A5 10 00 00 00 00 
{176} normal block at 0x00514BB8, 8 bytes long.
 Data: < q      > C8 71 84 10 04 00 00 00 
Object dump complete.

程序“[13260] mfctest.exe”已退出,返回值为 2 (0x2)。

注:实践证明,这是误报的内存泄漏。这个现象仅限于MFC Debug的情况,MFC Release不会。此外,Windows控制台应用程序也无此误报现象。



2、原因分析


之前在网上看过一篇文章,说是因为opencv有关的dll文件比mfc dll先加载导致的。在VS输出窗口可以看到,opencv_xxx.dll在mfc的相关dll之前加载。


“mfctest.exe”(Win32): 已加载“F:\tmp-source\cv420test\Debug\mfctest.exe”。已加载符号。


“mfctest.exe”(Win32): 已加载“C:\Windows\SysWOW64\ntdll.dll”。已加载符号。


“mfctest.exe”(Win32): 已加载“C:\Windows\SysWOW64\kernel32.dll”。已加载符号。


“mfctest.exe”(Win32): 已加载“C:\Windows\SysWOW64\KernelBase.dll”。已加载符号。


“mfctest.exe”(Win32): 已加载“F:\tmp-source\cv420test\Debug\opencv_core420d.dll”。已加载符号。


“mfctest.exe”(Win32): 已加载“F:\tmp-source\cv420test\Debug\tbb_debug.dll”。已加载符号。


“mfctest.exe”(Win32): 已加载“C:\Windows\SysWOW64\msvcp140d.dll”。已加载符号。


“mfctest.exe”(Win32): 已加载“C:\Windows\SysWOW64\vcruntime140d.dll”。已加载符号。


“mfctest.exe”(Win32): 已加载“C:\Windows\SysWOW64\ucrtbased.dll”。已加载符号。


“mfctest.exe”(Win32): 已加载“F:\tmp-source\cv420test\Debug\opencv_imgcodecs420d.dll”。已加载符号。

“mfctest.exe”(Win32): 已加载“F:\tmp-source\cv420test\Debug\opencv_imgproc420d.dll”。已加载符号。


“mfctest.exe”(Win32): 已加载“C:\Windows\SysWOW64\mfc140ud.dll”。已加载符号。

“mfctest.exe”(Win32): 已加载“C:\Windows\SysWOW64\advapi32.dll”。已加载符号。

“mfctest.exe”(Win32): 已加载“C:\Windows\SysWOW64\msvcrt.dll”。已加载符号。


但是这个办法真的能有效解决吗?未必!



3、网上分享的解决办法


在网上可以搜索到的解决办法,有以下四种,本人每个都动手实践了一下,


(1)把OpenCV编译成静态库,并且也在静态库中使用MFC


编译时有两种方案供选择:


A方案使用默认值,VC++ OpenCV源码工程->配置属性->C++->代码生成->运行库->多线程调试 (/MTd)和多线程 (/MT)

B方案是把运行库修改为多线程调试 DLL (/MDd)和多线程 DLL (/MD)

我们自己工程中使用OpenCV的静态库。然后:


如果是第A方案


VC++自己的工程->配置属性>常规>MFC的使用“ ,由“在共享 DLL 中使用 MFC”修改为“在静态库中使用 MFC”。

VC++自己的工程->配置属性->C++->代码生成->运行库->多线程调试 (/MTd)和多线程 (/MT)

VC++自己的工程的Debug和Release分别要使用OpenCV的Debug和Release静态库。不可以只使用Release的库。

(这种情况是很多人采取的做法,也是OpenCV官方推荐的解决办法之一。)


如果是B方案


VC++自己的工程->配置属性>常规>MFC的使用“ ,维持默认值不变,“在共享 DLL 中使用 MFC”。

VC++自己的工程->配置属性->C++->代码生成->运行库->多线程调试 DLL (/MDd)和多线程 DLL (/MD)

VC++自己的工程的Debug和Release分别要使用OpenCV的Debug和Release静态库。不可以只使用Release的库。

(firecat实践结果是不可行,编译通不过,error LNK2038: 检测到“RuntimeLibrary”的不匹配项: 值“MTd_StaticDebug”不匹配值“MDd_DynamicDebug”)


(2)把OpenCV编译成动态库,但是在静态库中使用MFC


VC++自己的工程->配置属性>常规>MFC的使用“ ,由“在共享 DLL 中使用 MFC”修改为“在静态库中使用 MFC”。


(这种情况是很多人采取的做法,也是OpenCV官方推荐的解决办法之一。)


(3)将opencv的dll二次封装到新的dll之中。


在mfc应用程序中不要出现opencv的函数和变量。自己写个库程序,封装成dll,然后延迟加载这个dll。


(firecat实践结果是不可行,仍然有内存泄露!)

(4)采取dll延迟加载技术


(不是太推荐!这个方法不能确保总是成功,firecat实践结果是有时成功,有时不成功)


仅针对debug模式,点击VC++项目属性,进入属性页,依次找到通用属性、链接器、输入、延迟加载的DLL选项,然后把OpenCV的bin文件下的所有dll的名称添加到延迟加载的DLL中。添加完之后,点击确定,然后再重新编译一下程序,就没有内存泄漏出现了。因为mfc下内存泄露主要是由于opencv dll先加载导致,因此只需要延迟加载即可。

image.png



设置完毕,编译,会提示警告,没关系,不变理会:


1>LINK : warning LNK4199: 已忽略 /DELAYLOAD:opencv_aruco420d.dll;未找到来自 opencv_aruco420d.dll 的导入

1>LINK : warning LNK4199: 已忽略 /DELAYLOAD:opencv_bgsegm420d.dll;未找到来自 opencv_bgsegm420d.dll 的导入

......

1>LINK : warning LNK4199: 已忽略 /DELAYLOAD:opencv_ximgproc420d.dll;未找到来自 opencv_ximgproc420d.dll 的导入

1>LINK : warning LNK4199: 已忽略 /DELAYLOAD:opencv_xobjdetect420d.dll;未找到来自 opencv_xobjdetect420d.dll 的导入

1>LINK : warning LNK4199: 已忽略 /DELAYLOAD:opencv_xphoto420d.dll;未找到来自 opencv_xphoto420d.dll 的导入

1>mfctest.vcxproj -> F:\tmp-source\cv420test\Debug\mfctest.exe

1>已完成生成项目“mfctest.vcxproj”的操作。


4、最后附上我的opencv debug dll动态库文件清单:


opencv_aruco420d.dll
opencv_bgsegm420d.dll
opencv_bioinspired420d.dll
opencv_calib3d420d.dll
opencv_ccalib420d.dll
opencv_core420d.dll
opencv_datasets420d.dll
opencv_dnn_objdetect420d.dll
opencv_dnn_superres420d.dll
opencv_dnn420d.dll
opencv_dpm420d.dll
opencv_face420d.dll
opencv_features2d420d.dll
opencv_flann420d.dll
opencv_fuzzy420d.dll
opencv_gapi420d.dll
opencv_hfs420d.dll
opencv_highgui420d.dll
opencv_img_hash420d.dll
opencv_imgcodecs420d.dll
opencv_imgproc420d.dll
opencv_line_descriptor420d.dll
opencv_ml420d.dll
opencv_objdetect420d.dll
opencv_optflow420d.dll
opencv_phase_unwrapping420d.dll
opencv_photo420d.dll
opencv_plot420d.dll
opencv_python3.dll
opencv_quality420d.dll
opencv_reg420d.dll
opencv_rgbd420d.dll
opencv_saliency420d.dll
opencv_shape420d.dll
opencv_stereo420d.dll
opencv_stitching420d.dll
opencv_structured_light420d.dll
opencv_superres420d.dll
opencv_surface_matching420d.dll
opencv_text420d.dll
opencv_tracking420d.dll
opencv_ts420d.dll
opencv_video420d.dll
opencv_videoio420d.dll
opencv_videostab420d.dll
opencv_xfeatures2d420d.dll
opencv_ximgproc420d.dll
opencv_xobjdetect420d.dll
opencv_xphoto420d.dll



OpenCV Release staticLib静态库文件清单,少部分lib需要从\opencv-4.2.0\build_x32_static\3rdparty拷贝

ippiw.lib
ippicvmt.lib
ittnotify.lib
tbb.lib
zlib.lib
libjpeg-turbo.lib
libwebp.lib
libpng.lib
libtiff.lib
libjasper.lib
IlmImf.lib
opencv_aruco420.lib
opencv_bgsegm420.lib
opencv_bioinspired420.lib
opencv_calib3d420.lib
opencv_ccalib420.lib
opencv_core420.lib
opencv_datasets420.lib
opencv_dnn_objdetect420.lib
opencv_dnn_superres420.lib
opencv_dnn420.lib
opencv_dpm420.lib
opencv_face420.lib
opencv_features2d420.lib
opencv_flann420.lib
opencv_fuzzy420.lib
opencv_gapi420.lib
opencv_hfs420.lib
opencv_highgui420.lib
opencv_img_hash420.lib
opencv_imgcodecs420.lib
opencv_imgproc420.lib
opencv_line_descriptor420.lib
opencv_ml420.lib
opencv_objdetect420.lib
opencv_optflow420.lib
opencv_phase_unwrapping420.lib
opencv_photo420.lib
opencv_plot420.lib
opencv_quality420.lib
opencv_reg420.lib
opencv_rgbd420.lib
opencv_saliency420.lib
opencv_shape420.lib
opencv_stereo420.lib
opencv_stitching420.lib
opencv_structured_light420.lib
opencv_superres420.lib
opencv_surface_matching420.lib
opencv_text420.lib
opencv_tracking420.lib
opencv_video420.lib
opencv_videoio420.lib
opencv_videostab420.lib
opencv_xfeatures2d420.lib
opencv_ximgproc420.lib
opencv_xobjdetect420.lib
opencv_xphoto420.lib




---


参考文献


https://stackoverflow.com/questions/9232837/how-to-remove-memory-leaks-between-opencv-1-1-and-mfc-6-0-without-linking-mfc-as


相关文章
|
4天前
|
计算机视觉
[Qt&MFC] 各种方式的图像读取(OpenCv、Halcon)
[Qt&MFC] 各种方式的图像读取(OpenCv、Halcon)
42 0
|
存储 人机交互 数据安全/隐私保护
OpenCV和MFC的超混沌图像加密
OpenCV和MFC的超混沌图像加密
116 0
OpenCV和MFC的超混沌图像加密
|
.NET C# 计算机视觉
为基于OpenCV的图像处理程序编写界面—关于QT\MFC\CSharp的选择以及GOCW的介绍
基于OpenCV编写图像处理项目,除了算法以外,比较重要一个问题就是界面设计问题。对于c++语系的程序员来说,一般来说有QT/MFC两种考虑。QT的确功能强大,特别是QML编写android界面很有一套(https://www.cnblogs.com/jsxyhelu/p/8286476.html),在树莓派上进行设计也很方便(https://www.cnblogs.com/jsxyhelu/p/7839062.html);但是使用QT的一个现实问题就是和现有平台的结合,比如客户需要将结果导出到excel中,使用QT就比较别扭(当然不是说不可以)。
2288 0
|
计算机视觉
基于opencv和mfc的摄像头采集代码(GOMFCTemplate2)持续更新
      编写带界面的图像处理程序,选择opencv+mfc是一种很好的选择;在读取摄像头数据方面,网上的方法很多,其中shiqiyu的camerads的方法是较好的。       基于现有资料,通过在实际项目中的积累,我总结出来一套结合opencv和mfc的摄像头采集框架。
1626 0
|
算法 计算机视觉 索引
基于Opencv和Mfc的图像处理增强库GOCVHelper(索引)
GOCVHelper(GreenOpen Computer Version Helper )是我在这几年编写图像处理程序的过程中积累下来的函数库。主要是对Opencv的适当扩展和在实现Mfc程序时候的功能增强。
1390 0
|
计算机视觉
1.0.1-学习Opencv与MFC混合编程之---播放AVI视频
资源源代码:http://download.csdn.net/detail/nuptboyzhb/3961639 版本1.0.1新增内容 Ø  新建菜单项,Learning OpenCV——> OpenCVr入门——>播放AVI视频。
936 0
|
计算机视觉
1.0.2-学习Opencv与MFC混合编程之---为播放AVI视频添加滑动条
源代码地址:http://download.csdn.net/detail/nuptboyzhb/3961642 版本1.0.2新增内容 Ø  全局变量和函数的添加: 在CVMFCview.cpp文件中增加全局变量和全局函数 //-----------------全局变量和函数-------...
877 0
|
计算机视觉
1.0.3-学习Opencv与MFC混合编程之---打开本地摄像头
源代码:http://download.csdn.net/detail/nuptboyzhb/3961643 版本1.0.3新增内容 打开摄像头 Ø 新建菜单项,Learning OpenCV——> OpenCVr入门——>打开摄像头(c) Ø 菜单项设置如下: Ø 建立类向导 Ø 编辑...
1022 0
|
计算机视觉
1.0.x-学习Opencv与MFC混合编程之---视频运动检测
源代码地址: http://download.csdn.net/detail/nuptboyzhb/3961668 版本1.0.x新增内容 视频运动检测 Ø 新建菜单项,Learning OpenCV——> OpenCVr入门——>视频运动检测 Ø 菜单项设置如下: Ø 建立类向导 ...
1024 0