Visual Studio之RelWithDebInfo模式,“被忽视”的编译模式

本文由Markdown语法编辑器编辑完成。

1. 背景:

在Visual Studio的编译模式选项中,一般有四个模式:Debug, Release, RelWithDebInfo, MinSizeRel。

大家一般对前两个模式比较多。Debug版本是调试版本,对代码不做任何优化,可以debug项目中的任意文件;Release版本是发行版本,顾名思义就是当程序开发完成后,程序的一个发布版,它对代码做了优化,因此速度会非常快,但是遗憾的是,release版本无法跟踪代码。

根据以上描述,debug和release版本各有自己的优势和缺陷。
debug版本为了追求更全面的调试信息而放弃了速度;
release版本为了追求性能优化而抛弃了调试信息。

如果用户既需要调试代码,又无奈于debug版本的速度,那么你便可以开始考虑RelWithDebInfo这个版本了。

顾名思义,从这个模式的名称来看,它是一种含有调试信息的Release版本。那么它相当于是结合了Debug和Release版本的优点的一个版本。

以下是Stackoverflow上面的关于比较Debug和RelWithDebInfo版本区别的描述:
http://stackoverflow.com/questions/1239845/build-mode-relwithdebinfo

The main differences being that in Debug mode, the executable produced isn’t optimized (as this could make debugging harder) and the debug symbols are included.

The difference between Debug and RelWithDebInfo is mentioned here:

RelWithDebInfo is quite similar to Release mode. It produces fully optimized code, but also builds the program database, and inserts dubug line information to give a debugger a good chance at guessing where in the code you are at any time.
RelWithDebInfo模式是非常近似于Release模式的。它生成出几乎完全优化的代码,而且也创建程序的数据库,插入一些调试信息以使调试人员能够有机会去跟踪你任意时刻正处于哪段代码中。

关于Debug和RelWithRebInfo版本的区别如下:
https://cmake.org/pipermail/cmake/2001-October/002479.html

本文将讲解如何利用这种模式,在即保证速度快的情况下,同时还可以添加断点并进行代码调试。你一旦了解了这个模式,我想以后完全可以抛弃掉Debug模式了。至少对于我而言,自从我学会了如何正确地使用RelWithDebInfo模式后,我就再也不想启动Debug模式了。

2. RelWithDebInfo模式:

首先Visual Studio在第一次安装并配置为Visual Studio C++开发环境后,默认就会有四种编译模式。分别为(按首字母排序):Debug, MinSizeRel, Release, RelWithDebInfo
这里写图片描述

这里注意:如果不是用VS的自建工程方式创建工程,而是用如CMake这样的工具生成工具时,有时候默认是不会生成MinSizeRel和RelWithDebInfo模式的。
比如用CMake编译VTK-6.3的源码时,在勾选了Grouped和Advanced的checkbox后,在下面的选项栏目中,在CMake那栏的CMAKE_CONFIGURATION_TYPES后,就会显示需要生成的编译模式,如果没有RelWithDebInfo这项,用户可以手动输入这个选项即可。
这里写图片描述

最常用的无疑是Debug和Release模式了,而在开发过程中,更是几乎要用Debug模式来调试代码和查找bug。但是,Debug模式由于所有工程全部附带了编译信息,不做任何优化,使得在实际调试时,会非常影响调试速度。如果仅仅是调试一两次还无所谓,但是对于一天要启动程序几十次甚至几百次的频繁调试,浪费的时间就非常可观了。

这里就以编译VTK-6.3的源码和例子作为示例,介绍如何使用RelWithDebInfo模式来调试代码。

2.1 在CMake中选择编译Examples。

将编译模式由原来的Debug模式切换到RelWithDebInfo模式,同时勾选BUILD栏目下的BUILD_EXAMPLES选项,编译VTK-6.3自带的例子。设置如下图所示。
这里写图片描述

待VTKExamples.sln项目生成以后,用VS开发这个工程文件,然后开始编译,直至项目中的所有例子工程都编译完成。
这里写图片描述

2.2 以例子工程中的Medical4为例进行调试。

在该工程名处点击右键,在弹出的选项中,选择Set as StartUp Project,将该工程设为启动工程,如下图所示。这样在运行时,便会进入这个工程的exe中了。
这里写图片描述

2.3 在Medical4.cxx中设置断点,准备调试

打开Medical4.cxx源码,在第45行处增加一个断点。
这里写图片描述

2.4 设置工程的优化选项,由默认的Maximize Speed(/O2)修改为Disabled(/Od)

这一步是最关键的。因为RelWithDebInfo模式默认是和Release模式一样,对工程进行最大性优化以提高速度。而因为我们要单独调试某一个工程,因此需要禁用它的优先,所以切换到Disabled模式,即不进行优化。
这里写图片描述

切换完成后,Optimization项修改为Disabled,如图所示。
这里写图片描述

2.5 重新编译要调试的工程

由于RelWithDebInfo模式下,所有的项目都以最优化方式编译,因此这些项目都是没有调试信息的。当把需要调试的工程设置为Disabled模式后,需要重新单独编译一下这个工程,才可以生成这个工程的编译信息。
这里写图片描述

2.6 以非调试模式启动程序(Start without Debugging)。

这一步也是非常关键的。因为我们不是要对整个工程项目进行调试,而只是对特定的某个工程进行调试,因此启动运行时为了保证速度,应该选择Start without Debugging这个选项。快捷键为Ctrl+F5。
这里写图片描述

2.7 设置抓取特定进程,进入断点调试。

点击菜单栏TOOLS选项,选择Attach to Process选项,准备抓取进程。
这里写图片描述

点击Attach to Process选项后,在弹出的窗口中会显示目前电脑中正在运行的进程,在Available Processes中。在这些正在运行的进程中选择Medical4.exe,再点击右下角的Attach按钮,则完成了抓取进程的设置。
这里写图片描述

2.8 断点调试

这里不太方便演示这一点。
原因在于,Medical4.exe是一个单独的应用程序。如果没有启动这个exe的时候,在Available Processes中是没有Medical4.exe这个进程的。但是如果启动了这个exe后,之前标注断点的语句已经运行完成。此时如果再Attach进程的话,已经无法进入断点了。

但是,如果是在一个比较大的项目中,工程之间存在相互调用的关系。那么在启动整个项目的exe后,在进程中便可以捕捉到。然后在后面需要调试的源码中增加断点,则当流程中运行到需要调用那个模块的时候,便会进入断点了。这样便实现了以Release的速度运行程序,而以Debug的方式来调试需要关注的代码段。

备注:

其实2.4的步骤,即将Optimization由Maximize Speed切换为Disabled不是必须的,也可以实现在RelWithDebInfo模式中调试代码。但是,这时,在调试的过程中,会发现进入断点后,程序运行比较奇怪。例如,如果有if…else分支时,有时候既会进入if分支,也会进入else分支,而且如果想查看某个代码段的变量值,会发现变量值无法显示或者显示结果异常。

因此,如果想得到最准确的调试信息,还是需要首先将要debug的那个工程,禁用最优化速度才可以。

完!

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

inter_peng

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值