VC 调试版(Debug Version)和发行版(Release Version)
调试是纠正或修改代码,使之可以顺利地编译、运行的过程。为此,VC IDE提供了功能强大的调试和跟踪工具。
1.1.1 调试版(Debug Version)和发行版(Release Version)
开发环境总是为你的工程创建调试版和发行版。在调试版里,我们排查各种可能的程序错误,然后制作成发行版以获得较好的信息。这就是调试版与发行版的区别:前者包含了较多调试信息,最终执行文件较大,性能较差;后者最终执行文件较小,性能更好。具体地讲,发行版和调试版区别有:
1. 调试版下,可以使用诊断和跟踪宏,如ASSERT和TRACE,MFC类的DUMP功能也定义在调试版下。
2. 额外的变量初始化。编译器会自动将你未初始化的变量逐每字节赋值为0xCC。
3. 内存分配监视。在调试版下,在堆上分配的内存都会记录,做额外的初始化(0xCD),在释放时,会将其内容逐字节置0xFD。
怎样配置调试版[C1] 或发行版?
调试版和发行版都可以从 Build | Configurations中增加,或者当这两个配置已存在的情况下,从Project | Settings命令下进行配置。两者在配置上主要有以下不同:
1. 两个版本应该配置成不同的输出文件夹。这在Project | Settings | General中的两个编辑框中设定。
2. 调试版下,程序应该链接Debug版的c运行时库、禁止代码优化,并在C++属性页中的Preprocessor类别中加上预定义标识符_DEBUG。在Link属性页中的Debug类别中,选中DebugInfo和Microsoft Format选框。
4. 发行版下,程序应该链接Release版的c运行时库、设置代码优化,不定义_DEBUG标识符,去掉DebugInfo选框中的选择。
1.1.2 排除编译错误
VC6.0的编译器可以报告大约1100个左右的错误,这还不包含警告。而在编译和调试过程中我们还不仅仅遇到编译错误,也可能遇到链接错误和其他错误,因此我们只能讲一些很常见、很重要的编译错误。对我们没有列出来的编译错误,解决它的最好办法是,在output窗口中将光标定位在输出行,然后按F1键以获得MSDN的帮助。如果MSDN的版本与你的VC不兼容,那么你可以用获得到Error xxxx作为关键字在MSDN中搜索。目前这些错误的说明帮助出现在Visual C++ Programmer's Guide中的Build Errors条目下。
并非错误
形如“Loaded 'C:\WINNT\system32\gdi32.dll', no matching symbolic information found.”这样的报告不是错误。一般情况下,我们只需要跟踪自己的源代码,检查在那里发生了什么错误。但有时候我们也想看看,如果一个错误报告在系统DLL里时究竟是怎么回事。Microsoft不愿意在系统DLL中包含调试信息,因此它提供调试符号帮助你跟踪。随VC6.0发行的有一个调试符号包,但其内容可能不能跟得上你操作系统版本。如果你需要适合你操作系统版本的调试符号,请到微软更新网站上下载。
l LNK2001错误
LNK2001错误报告一个不能识别的外部标识符。通常你使用一个函数或外部变量,都必须事先给出其声明,否则就会产生这样一个错误。可以从以下几个方面寻找原因:
1. 使用内联函数,但该内联函数定义在.cpp文件中,而不是在.h文件中。
2. 声明了函数或外部变量,但找不到它们的定义。
3. 程序入口设置错误,并且进一步提示_WinMain@16': Unresolved External Symbol或类似错误。在Windows程序中,程序并不是最先从WinMain()或Main()这样的函数处开始执行,而是从WinMainCRTStartup()或MainCRTStratup函数处开始执行。这四个函数(实际上是8个,每个函数都有UNICODE版和单字节版)必须配套。如果进入点是WinMainCRTStartup (),则它期待在你的程序中找到一个WinMain()函数,如果找不到,则发生上述错误。
4. 在程序中使用了线程启动函数_beginthread,但选择的链接库为LIBC.LIB。
其他错误见MSDN。
1.1.3 断点和跟踪
编译错误都是静态的,更多的错误发生在运行时。为了排除运行时的错误,首先需要的是能够使正在运行的代码停下来。VC6.0提供了多种断点设置。
l 位置断点
l 条件断点:可以设置以下条件为真时中断程序
1. 单变量值改变时
2. 单变量值判断条件中断,如K>0,i == 5等
3. 数组单元素或多元素值改变或值判断条件中断。
4. 指针:指针变量改变或指针所指内容改变
5. 监视固定内存值变化
6. 监视寄存器中值的变化,如 cs == 0等。
也可以直接输入断点设置表达式,其语法是:
①Advanced Syntax 详解
{[function],[source],[exe] } location
{[function],[source],[exe] } variable_name
{[function],[source],[exe] } expression
括在{}对中的是上下文设置,这三项中任意一项都可省略,但省略前面的项时,应注意保留逗号。如下面的设置
是错误的:
{File.c, File.exe} .143 - Bad
正确的设置如
{Fun} .143 这样在函数Fun的第143行设置了一个断点。
更详细的说明见下面的举例:
{[function],[source],[exe] } .100 - A line number (this may not work with some languages)
{[function],[source],[exe] } @100 - A line number (this works for all languages)
{[function],[source],[exe] } Traverse - A function name
{[function],[source],[exe] } CMyWindow::OnCall - A function name
{[function],[source],[exe] } 00406030 - A memory address (decimal)
{[function],[source],[exe] } 0×1002A - A memory address (hexadecimal)
{function,[source],[exe] } Label - A statement label. The context must include function since
Label is visible in the function’s scope.
更详细的帮助,查看Visual C++ Programer’s Guid中Setting Breakpoints When Values Change or Become True主题。
l 消息断点
l 异常断点
当程序发生异常时,我们应该立即停下来,看看发生了什么事情。默认地,当一个异常发生时,Debugger 将异常信息写到Output 窗口中,并根据你的选择决定是否立即中断程序。这个设置在Debug菜单中的Exceptions选项中提供。这里提供了两个选项Stop Always和Stop If Not Handled。当Stop If Not Handled被选中时,debugger仅仅往Output窗口中输出一条信息,而并不中止程序,除非没有这个异常最后也得不到处理。在有些情况下,这会是一个有些晚的时机。当Stop Always被选中时,debugger会在异常处理代码接管以前就中断程序。
1.1.4 查看和修改程序运行状态
开发环境提供了一系列的查看方式来临视甚至修改程序的运行状态。总共提供了六种查看窗口:
l Watch窗口
Watch窗口用来查看和解码中间变量,并允许你修改变量的值。Watch窗口共有四个Tab。每个Tab都是一个ListView,由两栏组成。左边一栏为变量名,右边一栏则为变量取值。只要在变量名栏输入变量名并回车,就可以得到当前变量的值。下面是一些特殊的用法:
1. 列出数组中前n个元素的值:arr,n
2. 查看UNICODE编码的字符串值:str,su
3. 已知消息值,查对应的宏:messageValue,wm
4. 查看窗口类标志(Window class flag):flagValue,wc
5. 查看当前线程最后错误报告:@err,hr
6. 查看COM库最后错误报告:@hres,hr
7. 查看当前寄存器值,把寄存器名当作变量名输入就可以了。
直接在右边栏输入新的取值,就会修改该变量的取值并发生作用。
l Variables窗口
这个窗口始终跟踪当前上下文中重要的变量取值。但不能增加对变量的跟踪。它包含三个Tab:
Auto窗口跟踪当前声明或前一个声明中使用的变量,当你从一个函数调用中跳出时,还可以显示函数的返回值。
Locals窗口显示对当前函数来说是局部的变量的取值。
This窗口显示this指针所指对象取值。
此外,在Variables窗口的上部,还有一个Context的组合框,可以用来切换当前查看的上下文。
l CallStack窗口
这个窗口显示了函数调用的情况。当你的程序出现一个断言时,你可以用这个窗口把函数调用顺序调出来,并且可以知道调用时传递参数的情况。双击窗口中列出的函数,可以定位到源代码中。
l Memory窗口
Memory窗口的上部是一个地址输入框。你可以在这里输入0×00400000,因为这时进程的起始点,所以毫不奇怪,你会看到MZ这两个字。Memory窗口支持定制显示格式,并支持表达式。
在Memory窗口的下面窗口处按右键,会出现一个菜单,允许你按单字节、双字节十六进制或四字节十六进制来显示内存的内容。
如果你愿意麻烦一点,还有办法得到更准确的显示。点Tools | Options,选择Debug属性页,在这里可以决定以什么形式显示内存内容以及从什么地址开始显示。这里提供了14种格式选项。此外,你还可以输入一个地址表达式。比如,如果要知道当前栈顶的情况,在这里输入ESP。
l Disassembly窗口
这个窗口可以用跟踪优化代码,或者是复杂表达式。
l Registers窗口
Registers窗口显示所有寄存器值,并允许你修改。它与Watch窗口的区别是,你不需要记住寄存器名,它总是把所有寄存器值给你列出来。
1.1.5 使用断言和诊断[1]
VC提供了两个断言宏:ASSERT和VERIFY。两者的区别是,在发行版中,ASSERT行不会执行,因为在发行版中,ASSERT宏被定义成
#define ASSERT /##/
这样这行代码被注释掉,从而不会被编译。VERIFY宏在发行版中被定义成
#define VERIFY
这样VERIFY后面的代码仍然加入编译,从而得到执行。
在你掌握了这两个断言的区别后,我们将只讲述ASSERT宏。ASSERT是一个带参宏,其参数允许是一个表达式。当表达式的值为假时,程序发生中断并提示你是否进行调试。
除了使用条件判断表达式外,ASSERT(0)也很有用。它始终引起一个断言错,并提示你是否调试。你可以把它放在一些你不期望程序运行到达的路径上,如果事情一旦发生,则可以直接进行调试。
VC还提供TRACE宏,以及它的姊妹宏TRACE0,TRACE1,TRACE2,TRACE3。TRACE宏的语法类似于printf,包括格式字符串的规定也是一致的。后面三个宏限定你使用一个格式字符串和一至三个变量。TRACE输出到Output窗口,如果工具MFC TRACER中设置为允许的话。
MFC还提供了对象诊断工具,即名为Dump的函数。MFC库中每个从CObject继承的类都有Dump的能力。如果你从MFC类库中派生了某个类,在有必要的情况下,最好重载这个函数。要记住,你重载的函数应该调用基类的Dump函数。另外,Dump函数只在调试版下可用。因此重载的函数也应该括在#ifdef _DEBUG宏中。
VC 调试版(Debug Version)和发行版(Release Version)的更多相关文章
- idea编辑项目出现【Information:java: javacTask: 源发行版 7 需要目标发行版 1.7】
在编译项目时候出现问题: Information:java: javacTask: 源发行版 7 需要目标发行版 1.7 解决方案:按着图片操作,这几个地方设置的一样就可以了
- Information:java: javacTask: 源发行版 8 需要目标发行版 1.8
原文链接:https://blog.csdn.net/idiot_qi/article/details/105149846 创建新maven项目跑main,出现这个编译异常 网上找了找,记录一下以备不 ...
- IDEA Java 源发行版 8 需要目标发行版 1.8
[问题记录] maven新建的一个项目,需要到一些java8的一些特性,但是在编译的时候就报错了,提示这样的错误. 我是在用二进制字面量出现的这个问题,二进制自变量是Java7的特性, 你可以这样写 ...
- Embedded Linux Primer----嵌入式Linux基础教程--2.4节--嵌入式Linux发行版
嵌入式Linux发行版 究竟什么是Linux发行版?在Linux内核引导之后,它期望找到并挂载根文件系统.当一个匹配的根文件系统已经挂载上,启动脚本开始运行大量程序和系统要求的工具.这些程序经常调用其 ...
- 多个Linux发行版安装ss服务端
本文仅做技术探讨,请在遵守相应的法律法规的前提下使用. Centos 7一键安装脚本 简单快捷,随机生成密码,默认端口默认加密类型 bash <(curl -s http://morning.w ...
- 最适合和最不适合新手使用的几款 Linux 发行版
大多数知名的Linux发行版都属于"比较容易使用"这一类.一些观察人士可能会驳斥这个观点,但事实上,说到Linux,大多数并非从事IT或软件开发工作的人会被最容易的使用体验所吸引. ...
- Linux发行版
Linux 发行版(英语:Linux distribution,也被叫做GNU/Linux 发行版),为一般用户预先集成好的Linux操作系统及各种应用软件.一般用户不需要重新编译,在直接安装之后,只 ...
- 2016年如何选择 Linux 发行版
不管是在企业级应用还是在消费者领域,2015 对于 Linux 来说都是极其重要的一年.作为一个从 2005 年就开始使用 Linux 的老用户,我有幸见证了 Linux 过去这 10 年里的重大发展 ...
- Linux发行版:CentOS、Ubuntu、RedHat、Android、Tizen、MeeGo
Linux,最早由Linus Benedict Torvalds在1991年开始编写.在这之前,Richard Stallman创建了Free Software Foundation(FSF)组织以及 ...
- Linux 大爆炸:一个内核,无数发行版
即使你是一个 Linux 新人,你可能也已经知道它不是一个单一的.整体的操作系统,而是一群项目.这个星座中不同的“星”组成了“发行版”.每个都提供了自己的 Linux 模式. 感谢这一系列发行版所提供 ...
随机推荐
- (转)注解用法详解—@@SuppressWarnings
一.前言 编码时我们总会发现如下变量未被使用的警告提示: 上述代码编译通过且可以运行,但每行前面的“感叹号”就严重阻碍了我们判断该行是否设置的断点了.这时我们可以在方法前添加 @SuppressWar ...
- (转)Spring事务管理(详解+实例)
文章转自:http://blog.csdn.net/trigl/article/details/50968079 写这篇博客之前我首先读了<Spring in action>,之后在网上看 ...
- map映照容器(常用的使用方法总结)
map映照容器的数据元素是由一个键值和一个映照数据组成的,键值和映照数据之间具有一一对应的关系.map与set集合容器一样,不允许插入的元素的键值重复. /*关于C++STL中map映照容器的学习,看 ...
- vue简单的脚手架搭建项目
第一步 node环境安装 1.如果本机没有安装node运行环境,下载node安装包进行安装 下载地址:https://nodejs.org/en/或者http://nodejs.cn/ 第二步 nod ...
- css中添加屏幕自适应方法(rem)
css中添加屏幕自适应方法(rem) 只需要在公共css文件中添加下面代码:设计稿以750px,基础字体为20px为例,兼容性高,使用过程中px转化为rem即可 /*竖屏*/ @media scree ...
- Docker 为 ASP.NET Core Web 应用程序生成 Docker 映像,创建并运行多个容器
1.为 ASP.NET Core 应用程序生成 Docker 映像 下载这个事例项目:https://github.com/dotnet/dotnet-docker/tree/master/sampl ...
- Android.mk 中常用“LOCAL_” 变量
编写模块的编译文件,实际就是定义一系列以“LOCAL_”开头的编译变量,因此我们有必要弄明白这些变量的具体含义.下面是一些经常使用的LOCAL_编译变量的说明: 变量名 说明 LOCAL_ASSET_ ...
- 诡异的楼梯(bfs)hdu1180
诡异的楼梯 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 131072/65536 K (Java/Others)Total Submiss ...
- 一些减少代码量、提高开发效率的利器(Java)
Spring Boot mybatis-plus代码生成器和自带CRUD接口 lombok 库: Apache Commons & guava AOP Java8: stream & ...
- php命令行按模板生成应用的入口文件
接着这篇文章php命令行生成项目结构 继续改造: ghostwu@dev:~/php/php1/12$ tree . ├── app │ └── index.php ├── core │ ├─ ...