环境:VS2012新建一个单线程MFC工程,缺省设置:在共享 DLL 中使用 MFC,使用 Unicode 字符集
问题:就两句话CvCapture * capture = cvCreateFileCapture( fn ); cvReleaseCapture(&capture);内存泄露无数。
方法:查找网站无数未果,想想会不会是项目字符集(缺省使用 Unicode 字符集)的问题?随即改成“使用多字节字符集“。
结果:运行正常,无内存泄漏。
原因:动态MFC使用方式下链接了OpenCV的debug动态库,无论用什么字符集都会内存泄露。具体分析如下:
因为后续又发现一个问题,只要定义了IplImage* m_img;就有内存泄露。最后是把”在共享 DLL 中使用 MFC“改为”在静态库中使用 MFC“解决了。 于是就很想弄明白opencv的库是咋个回事,进行了如下测试。
下载的OpenCV带了两种库,动态lib和静态staticlib,里面都包含了debug和release两种库。
对应的MFC程序也分为两种:在共享 DLL 中使用 MFC(简称动态MFC)、在静态库中使用 MFC(简称静态MFC)。
经过测试:静态MFC可以用OpenCV动态和静态库,动态库两个版本都可以;但是静态库只能debug对debug,release对应release。而动态MFC只能用OpenCV动态库,具体结果见下表。表中的链接错误一般为error LNK2005、error LNK2038。此外需注意,静态MFC比动态增加了zlib、libjpeg、libtiffd.lib、libpng、libjasper、llmImf、vfw32(不分d)等库。
表1 动静态MFC使用与OpenCV库的对应关系
--------------------------动态lib/debug 动态lib/release | 静态lib/debug 静态lib/release
静态 MFC/debug 正常 正常 | 正常 链接错误
静态 MFC/release 正常 正常 | 链接错误 正常
----------------------------------------------------------------------------------------------------------------------------
动态MFC/debug 内存泄漏 正常 | 链接错误 链接错误
动态MFC/release 正常 正常 | 链接错误 链接错误
结论:看来使用highgui函数出现内存泄露,实质是动静态MFC使用与OpenCV库的对应关系,与字符集没啥大关系,只是表象。再就是上面的MFC动态使用时出现问题。可以看出静态 MFC使用还是蛮好,正常的概率很高达到75%,建议采用。如果使用动态MFC,那也要使用OpenCV的release动态库。 具体原因是否和网站提供库的编译设置有关不得而知,不知是否普遍现象,待证实。
另外建议,尽量不要采用在项目属性中的配置属性->链接器->输入->附加依赖项中加入库文件名的方式。 而采用下面的方式加在CPP文件中的方式。
#ifdef _DEBUG
#pragma comment(lib,"opencv_core249d.lib")
#pragma comment(lib,"opencv_highgui249d.lib")
#pragma comment(lib,"opencv_video249d.lib")
#pragma comment(lib,"opencv_ml249d.lib")
#pragma comment(lib,"opencv_legacy249d.lib")
#pragma comment(lib,"opencv_imgproc249d.lib")
#pragma comment(lib,"vfw32.lib")
//#pragma comment(lib,"zlibd.lib")// 使用staticlib下的静态库需要包含
//#pragma comment(lib,"libjpegd.lib")
//#pragma comment(lib,"libtiffd.lib")
//#pragma comment(lib,"libpngd.lib")
//#pragma comment(lib,"libjasperd.lib")
//#pragma comment(lib,"IlmImfd.lib")
#pragma comment(lib,"blas_win32_MTd.lib")
#pragma comment(lib,"lapack_win32_MTd.lib")
#pragma comment(lib,"FreeImaged.lib")
#else // _DEBUG
#pragma comment(lib,"opencv_core249.lib")
#pragma comment(lib,"opencv_highgui249.lib")
#pragma comment(lib,"opencv_video249.lib")
#pragma comment(lib,"opencv_ml249.lib")
#pragma comment(lib,"opencv_legacy249.lib")
#pragma comment(lib,"opencv_imgproc249.lib")
#pragma comment(lib,"vfw32.lib")
//#pragma comment(lib,"zlib.lib")// 使用staticlib下的静态库需要包含
//#pragma comment(lib,"libjpeg.lib")
//#pragma comment(lib,"libtiff.lib")
//#pragma comment(lib,"libpng.lib")
//#pragma comment(lib,"libjasper.lib")
//#pragma comment(lib,"IlmImf.lib")
#pragma comment(lib,"blas_win32_MT.lib")
#pragma comment(lib,"lapack_win32_MT.lib")
#pragma comment(lib,"FreeImage.lib")
#endif