一般程序在Debug版能够运行,在Release版就不能运行,啥原因?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了一般程序在Debug版能够运行,在Release版就不能运行,啥原因?相关的知识,希望对你有一定的参考价值。

上次调试一个程序的时候,发现使用Debug版,程序就能正常稳定的运行,而Release版就会出现内存泄露的问题,请问这样的问题怎么样解决?是什么地方出错了?

内存泄漏吧,因为debug版本有自己的内存管理所以比较容易掩盖错误,用boundChecker查查吧 参考技术A 你也可以用Visual Leak Detector 这个软件检测内存泄漏,比较专业的。

OpenCV与Debug和Release模式

1.Release和Debug的区别

  Release版称为发行版,Debug版称为调试版。
  Debug中可以单步执行、跟踪等功能,但生成的可执行文件比较大,代码运行速度较慢。Release版运行速度较快,可执行文件较小,但在其编译条件下无法执行调试功能。
  Release的exe文件链接的是标准的MFC DLL(Use MFC in a shared or static dll)。这些DLL在安装Windows的时候已经配置,所以这些程序能够在没有安装Visual C++的机器上运行。而Debug版本的exe链接了调试版本的MFC DLL文件,在没有安装Visual C++的机器上不能运行,因为缺相应的DLL,除非选择use static dll when link。

         Debug 和 Release 并没有本质的区别,他们只是VC预定义提供的两组编译选项的集合,编译器只是按照预定的选项行动。如果我们愿意,我们完全可以把DebugRelease的行为完全颠倒过来。当然也可以提供其他的模式,例如自己定义一组编译选项,然后命名为MY_ABC等。习惯上,我们仍然更愿意使用VC已经定义好的名称。
   Debug版本包括调试信息,所以要比Release版本大很多(可能大数百K至数M)。至于是否需要DLL支持,主要看你采用的编译选项。如果是基于ATL的,则DebugRelease版本对DLL的要求差不多。如果采用的编译选项为使用MFC动态库,则需要MFC42D.DLL等库支持,而Release版本需要MFC42.DLL支持。Release不对源代码进行调试,不考虑MFC的诊断宏,使用的是MFC Release库,编译时对应用程序的速度进行优化,而Debug则正好相反,它允许对源代码进行调试,可以定义和使用MFC的 诊断宏,采用MFC Debug库,对速度没有优化。
         既然DebugRelease仅仅是编译选项的不同,那么为什么要区分DebugRelease版本呢?
   DebugRelease,在我看来主要是针对其面向的目标不同的而进行区分的。Debug通常称为调试版本,通过一系列编译选项的配合,编译的结果通常包含调试信息,而且不做任何优化,以为开发人员提供强大的应用程序调试能力。而Release
通常称为发布版本,是为用户使用的,一般客户不允许在发布版本上进行调试。所以不保存调试信息,同时,它往往进行了各种优化,以期达到代码最小和速度最优。为用户的使用提供便利。

 

2.Opencv在Release和Debug下配置的区别
  
上文已经说明Release和Debug的区别,所以Opencv在Debug和Release不同环境下都需要进行对应的配置的。
  另外我们需要注意,Opencv并不是Windows下标准库,所以它的DLL文件在安装Windows的时候并不会随之配置。也就是说Release和Debug环境下,Opencv库都有对应的Lib和DLL文件,我们在对应模式下都需要配置。并且在发行程序exe之后,随之的DLL文件也需要放置在同一文件夹中,否则程序会报错找不到对应的DLL文件。

 

 永久配置结果:

 

3. 直接运行利用debug和release生成的exe

      按照下面链接配置好opencv两种版本以后,建立新的项目,在 项目》属性》C/C++》代码生成中将运行库改为MT,然后利用release调试,release文件夹下生成的exe文件则可以直接双击运行。同理如果想直接双击运行debug文件夹下的exe文件,则将下图中的配置选为debug,然后将运行库选择为MTd即可。可以看到运行库不止这MT和MTd两个选项,这两个选项叫做静态编译。而剩下的连个选项MD和MDd叫做动态编译。

      关于运行库的选项:

  • 静态编译:debug状态下:MTd    release状态下:MT
  • 动态编译:debug状态下:MDd    release状态下:MD

  即区别debug或release的标志则是有无小写字母 d ,有则为debug,无则为release。那么静态编译和动态编译的又是什么呢?下面介绍。

 

4. 静态编译和动态编译

       动态编译的生成的可执行文件的exe小,但是运行需要系统环境具有相关的dll和lib文件,就是动态调用系统相关的文件才能运行;静态编译生成的可执行文件exe大,但是运行的时候不依赖于系统环境所依赖的dll和lib等环境问题,在编译的时候已经这些dll相关文件编译进了exe文件,所以exe文件较大。所以需要自己创建的工程需要在别的电脑上运行,考虑到稳定性,同时对执行文件的大小没有要求的话还是尽量选择静态编译。

  • 静态编译将导出声明和实现都放在lib中。编译后所有代码都嵌入到宿主程序。
  • 静态编译的优点是编写出来的程序不需要调用DLL和载入函数,直接可以当成程序的一部分来使用。
  • 静态编译的缺点也是显而易见的,使用静态编译的程序体积会比动态编译大,原因是函数的实现被嵌入为程序代码的一部分。
      动态LIB文件相当于一个C语言中的h文件,是函数导出部分的声明,而不将实现过程嵌入到程序本身中,编译后只是将函数地址存在宿主程序中,运行到调用函数是调用DLL并载入函数来实现函数的具体操作。动态编译的可执行文件需要附带一个的动态链接库,在执行时,需要调用其对应动态链接库中的命令。

       优缺点:所以动态编译的优点一方面是缩小了执行文件本身的体积,另一方面是加快了编译速度,节省了系统资源。缺点一是哪怕是很简单的程序,只用到了链接库中的一两条命令,也需要附带一个相对庞大的链接库;二是如果其他计算机上没有安装对应的运行库,则用动态编译的可执行文件就不能运行。静态编译就是编译器在编译可执行文件的时候,将可执行文件需要调用的对应动态链接库(.so)中的部分提取出来,链接到可执行文件中去,使可执行文件在运行的时候不依赖于动态链接库。所以其优缺点与动态编译的可执行文件正好互补。

 

 5.  OpenCV && VS静态编译和动态编译

         MinGW编译器目前仅能编译OpenCV2.x.x版本,OpenCV3.x.x并不支持MinGW编译器。最重要的是,OpenCV使用的Intel的IPP库是没有MinGW版本的,最直观的差别就是,使用OpenCV开发的实时图像处理程序在处理速度上,VC版本要比MinGW版本快至少一倍。所以在windos平台上使用OpenCV,最好还用微软自家的编译器。

         OpenCV官方默认使用动态链接库的形式发布,平时写OpenCV程序用于学习和研究就算了,当程序需要发布时,尤其是程序需要拷到没有OpenCV环境的机器上运行时,一堆的动态链接库弄得好烦,而且OpenCV3.1官方发布版本默认不包含vc10(也就是vs2010的编译器)的库,只好重新尝试编译。关于opencv支持那哪个vs的编译器,可以打开自己的opencv包:

可以看到opencv2.4.13版本支持的编译器有vc11和vc12,分别对应的VS版本为 visual Studio 2012 和  visual Studio 2013.

vc10, vc11, vc12 分别表示VS2010, VS2012, VS2013的Visual Studio使用的编译器版本,根据自己的VS版本来填写正确的编译器版本号。

编译前,需要提前下载并安装好Cmake和VS2010,并下载好OpenCV3.1的源代码。  

想在没有opencv和vs的电脑上运行 VS编译好的exe文件,则需要利用release模式(考虑到其他电脑没有VS)下静态编译(考虑到其他电脑不存在opencv的动态依赖库,依赖性小方便,就是生成的exe大些,可选)或动态编译(将对应需要的dll拷贝到exe的执行目录下,这种虽然文件多,但是易操作,也可选)。选哪种都行具体看自己的项目。

具体过程可参考;OpenCV3.1 VS2010静态编译和动态编译   和   [opencv]OpenCV项目的动态编译和静态编译

 

6. 补充: .dll文件和lib文件

1)Dll(Dynamic Link Library

       DLL(Dynamic Link Library)文件:动态链接库文件
       在Windows中,许多应用程序并不是一个完整的可执行文件,它们被分割成一些相对独立的动态链接库,即DLL文件,放置于系统中。当我们执行某一个程序时,相应的DLL文件就会被调用。一个应用程序可使用多个DLL文件,一个DLL文件也可能被不同的应用程序使用,这样的DLL文件被称为共享DLL文件。
特点:
(1)使用较少的资源(当多个程序使用同一个函数库时,DLL 可以减少在磁盘和物理内存中加载的代码的重复量)
(2)推广模块式体系结构
(3)简化部署和安装(当 DLL 中的函数需要更新或修复时,部署和安装 DLL 不要求重新建立程序与该 DLL 的链接。此外,如果多个程序使用同一个 DLL,那么多个程序都将从该更新或修复中获益。当您使用定期更新或修复的第三方 DLL 时,此问题可能会更频繁地出现)
 
2)Lib文件
       LIB有两种,一种是静态库,比如C-Runtime库,这种LIB中有函数的实现代码,一般用在静态连编上,它是将LIB中的代码加入目标模块(EXE或者DLL)文件中,所以链接好了之后,LIB文件就没有用了。一种LIB是和DLL配合使用的,里面没有代码,代码在DLL中,这种LIB是用在静态调用DLL上的,所以起的作用也是链接作用,链接完成了,LIB也没用了。至于动态调用DLL的话,根本用不上LIB文件。 目标模块(EXE或者DLL)文件生成之后,就用不着LIB文件了。
 
 
 
总结:
编译模式有静态与动态编译,编译选项有debug和release。
对于同一种编译模式下,debug生成的exe比release生成的exe要大,原因:Debug版本包括调试信息,所以要比Release版本大很多(可能大数百K至数M)。
对于同一种编译选项下,静态编译比动态编译生成的exe要大,原因:静态编译将相应的dll也编译进exe中,而动态编译的可执行文件exe小,不过另外附带一个动态链接库。
即生成的exe大小:静态>动态, debug>release
 
 
7. 如何在其他电脑上(无VS、Opencv)上运行exe
7.1 第一种方法:release方式,动态编译

我的环境windows10 + Visual Studio 2013 + opencv2.4.13

步骤:

1.打开项目配置页->c/c++->代码生成->运行库,设置成多线程调试DLL(/MD)(release版的动态编译程序选择MD,这一步是为了添加程序运行需要的运行库

2.利用VS编译生成exe,然后把对应的dll库拷贝到exe的文件夹下面。将此文件夹作为一个整体发送到其他电脑。(具体需要拷贝哪些dll库可以使用visual studio的dependents查看,方法如下)

使用dependents查看exe所需要的dll库

  • 开始->所有程序->Microsoft Visual Studio 2010 ->Visual Studio Tools->VS2013 x86本机工具命令提示 
  • 跳转到exe所在根目录下,输入dumpbin /dependents main.exe,就会有如图所示结果。

我们需要添加三个opencvdll库,除此还需额外添加opencv_ffmpeg247.dll,不然总提示读取视频失败。下面的几个DLL文件在上面步骤一修改运行库时就已经添加了。

 
 
7.2 第二种方法:release方式,静态编译
       首先再解释一次为啥不用debug模式:vs2013编译项目有两个版本:Debug和Release,在Debug模式下生成的exe需要vs2013的一些Debug库文件支持,就是说在没有vs2013的电脑上是无法正常运行的,所以要在Release模式下面编译项目。

步骤:

1、把工程调成Release模式。

2、右键项目->属性打开项目属性页面,首先在配置属性->常规页面,如果是MFC程序,则在“MFC的使用”选择“在静态库中使用MFC”。然后在配置属性->C/C++ ->代码生成页面,“运行库”里面选“多线程(/MT)”。

3、然后生成重新解决方案,生成了之后会在项目的Release文件夹下面看到一个exe文件和一个pdb文件(注意:这不是用静态库生成的)。

4、打开opencv2-4-13的安装目录,在“安装路径opencv\\build\\x86\\vc12\\bin目录下将所有的Release版本(不带字母d的dll)的动态库文件拷贝到Release文件夹里面,跟exe文件放在一起。这样生成的exe程序就可以在其他电脑上面运行了。

 

参考于:

http://blog.csdn.net/FX677588/article/details/72622011

https://www.zhihu.com/question/24400428    知乎上的关于opencv debug和release版本的永久配置

http://blog.csdn.net/leo2007608/article/details/38963947    CSDNS上的opencv debug和release版本的永久配置

http://www.cnblogs.com/xujianqing/p/5356559.html    关于opencv转换debug和release版本出现的问题。

如何生成能在没有安装opencv库及vs2010环境的电脑上运行的exe文件

 

关于debug和release的问题,个人觉得还是分别建两个新项目属性OpencvDebug和OpencvRelease比较方便。

 

以上是关于一般程序在Debug版能够运行,在Release版就不能运行,啥原因?的主要内容,如果未能解决你的问题,请参考以下文章

在C++中,Debug版本能顺利运行,但Release版本有时却不能运行,为啥?

移动端ionic cordova 打包debug调试版release发布版

debug与release

Fortran 编译过程中,debug和release最大的区别是啥?

VS环境下Debug和Release版本的区别

VC中release和debug版本的区别?