Visual C++开发工具与调试技巧

来源:互联网 发布:网络参与赌博如何定罪 编辑:程序博客网 时间:2024/05/09 05:58

Visual C++开发工具与调试技巧

(此文章旨在集合一些高人在调试方面的经验技巧以便大家分享,并非原创,在此特别感谢那些创作与分享这些经验的前辈们)

自己总是用VC平台来开发东西,但是有时候总是出这样那样的问题,呵呵,总是需要上网查资料来解决,在这里把自己用到上网查的一些技巧摘录如下,希望对大家有用,省去大家再去搜索的烦恼。 

1.
如何在Release状态下进行调试 
Project
>Setting>ProjectSetting对话框,选择Release状态。C/C++标签中的CategoryGeneralOptimizationsDisable(Debug)Debut infoProgram Database。在Link标签中选中Generate debug info复选框。 

注:只是飞鸽传书一个介乎DebugRelease的中间状态,所有的ASSERTVERIFY都不起作用,函数调用方式已经是真正的调用,而不查表,但是这种状态下QuickWatch、调用队列跟踪功能仍然有效,和Debug版一样。 

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

3. ASSERT
VERIFY有什么区别 
ASSERT
里面的内容在Release版本中不编译,VERIFY里面的内容仍然翻译,但不再判断真假。所以后者更安全一点。 
例如ASSERT(file.Open(strFileName)) 
一旦到了Release版本中,这一行就忽略了,file根本就不Open()了,而且没有任何出错的信息。如果用VERIFY()就不会有这个问题。 

4.Workspace
Project之间是什么样的关系 
每个Workspace可以包括几个project,但只有一个处于Active状态,各个project之间可以有依赖关系,在projectSetting..中可以设定,比如那个Active状态的project可以依赖于其他的提供其函数调用的静态库。 

5.
如何在非MFC程序中使用ClassWizard 
在工程目录下新建一个空的.RC文件,然后加入到工程中就可以了。 

6.
如何设置断点 
F9在当前光标处增加一个断点和取消一个断点。 
另外,在编辑状态下,按Ctrl+B组合键,弹出断点设置对话框。然后单击【Condition…】按钮弹出设置断点条件的对话框进行设置。 

7.
在编辑状态下发现成员变量或函数不能显示提示是如何打开显示功能 
这似乎是目前这个VisualC++ 6.0版本的一个bug,可按如下步骤使其正常,如再出现,可如法炮制: 
(1)
关闭Project 
(2)
删除工程名.ncb”文件 
(3)
重新打开工程 

8.
如何将一个通过ClassWizard生成的类彻底删除 
首先在工作区的FileView中选中该类的.h.cpp文件,按delete删除,然后在文件管理器中将这两个文件删除,再运行ClassWizard,这时出现是否移走该类的提示,选择remove就可以了。 

9.
如何将在workspace中消失的类找出来 
打开该类对应的头文件,然后将其类名随便改一下,这个时候工作区就会出现新的类,再将这个类改回原来的名字就可以了。 

10.
如何清除所有的断点 
菜单【Edit】->Breakpoints…】,打开“Breakpoints”对话框,单击【Remove All】按钮即可。快捷键是“Ctrl + Shift + F8” 

11.
如何再ClassWizard中选择未列出的信息 
打开“ClassWizard”对话框,然后切换到“Class Info”页面。改变“Message filter”,如选择“Window”“Message”页面就会出现Window的信息。 

12.
如何检测程序中的括号是否匹配 
把光标移动到需要检测的括号前面,按快捷键“Ctrl+ ]”。如果括号匹配正确,光标就跳到匹配的括号处,否则光标不移动,并且机箱喇叭还会发出一声警告。 

13.
如何查看一个宏(或变量、函数)的定义 
把光标移动到要查看的一个宏上,就比如说最常见的DECLARE_MAP_MESSAGE上按一下F12(或右键菜单中的相关菜单),如果没有建立浏览文件,就会出现提示对话框,按【确定】按钮,然后就会跳到该宏(或变量、函数)定义的地方。 

14.
如何添加Lib文件到当前工程 
单击菜单【Project】->Settings…】弹出“Project Setting”对话框,切换到“Link”标签页,在“Object/library modules”处输入Lib文件名称,不同的Lib之间用空格格开。 

15.
如何快速删除项目下的Debug文件夹中临时文件 
在工作区的FileView视图中选中对应的项目,单击右键弹出菜单,选择【Clean(selection only)】菜单即可。 

16.
如何快速生成一个现有工程除了工程名外完全相同的新工程 
在新建工程的“New”对话框中选择“Custom Appwizard”项,输入新工程的名字,单击【OK】按钮。出现“Custom AppWizard”项,输入新工程的名字,单击【OK】按钮。出现“Custom AppWizardStep 1 of 2”对话框,选择“An existing Project”项,单击【Next】按钮。出现“Custom AppWizardStep 2 of 2”对话框,选择现有工程的工程文件名,最后单击【Finish】按钮。编译后就生成一个与现有工程相同但可以重新取名的工程AppWizard 
现在就可以项用MFCAppWizard一样用这个定制的向导。如果不想用了,可以在VisualC++ 6.0安装目录下Common/MSDev98/Template目录中删除该Wizard对应的.awx.pdb文件。 

17.
如何解决Visual C++ 6.0不正确连接的问题 
情景:明明改动了一个文件,却要把整个项目全部重新编译链接一次。刚刚链接好,一运行,又提示重新编译链接一次。 
这是因为出现了未来文件(修改时间和创建时间比系统时间晚)的缘故。可以这样处理:找到工程文件夹下的debug目录,将创建和修改时间都比系统时间的文件全部删除,然后再从新“Rebuild All”一次。 

18.
引起LNK2001的常见错误都有哪些 
遇到的LNK2001错误主要为:unresolved external symbol “symbol” 
如果链接程序不能在所有的库和目标文件内找到所引用的函数、变量或标签,将产生此错误信息。 
一般来说,发生错误的原因有两个:一是所引用的函数、变量不存在,拼写不正确或者使用错误;其次可能使用了不同版本的链接库。以下是可能产生LNK2001错误的原因: 
<1>
由于编码错误导致的LNK2001错误 
(1)
不相匹配的程序代码或模块定义(.DEF)文件导致LNK2001。例如,如果在C++源文件了内声明了一变量“var1”,却试图在另一个文件内以变量“var1”访问改变量。 
(2)
如果使用的内联函数是在.cpp文件内定义的,而不是在头文件内定义将导致LNK2001错误。 
(3)
调用函数时如果所用的参数类型和头函数声明时的类型不符将会产生LNK2001错误。 
(4)
试图从基类的构造函数或析构函数中调用虚拟函数时将会导致LNK2001错误。 
(5)
要注意函数和变量的可公用性,只有全局变量、函数是可公用的。静态函数和静态变量具有相同的使用范围限制。当试图从文件外部方位任何没有在该文件内声明的静态变量时将导致编译错误或LNK2001错误。 
<2>
由于编译和联机的设置而造成的LNK2001错误 
(1)
如果编译时使用的是/NOD(/NODERAULTLIB)选项,程序所需要的运行库和MFC时将得到又编译器写入目标文件模块,但除非在文件中明确包含这些库名,否则这些库不会被链接进工程文件。这种情况下使用/NOD将导致LNK2001错误 
(2)
如果没有为wWinMainCRTStartup设定程序入口,在使用UnicodeMFC时将出现“unresolved external on _WinMain@16”LNK2001错误信息。 
(3)
使用/MD选项编译时,既然所有的运行库都被保留在动态链接库之内,源文件中对“func”的引用,在目标文件里即对“__imp__func”的引用。如果试图使用静态库LIBC.LIBLIBCMT.LIB进行链接,将在__imp__func上发生LNK2001错误。如果不使用/MD选项编译,在使用MSVCxx.LIB链接时也会发生LNK2001错误。 
(4)
使用/ML选项编译时,如用LIBCMT.LIB链接会在_errno上发生LNK2001错误。 
(5)
当编译调试版的应用程序时,如果采用发行版模态库进行链接也会产生LNK2001错误;同样,使用调试版模态库链接发行版应用程序时也会产生相同的错误。 
(6)
不同版本的库和编译器的混合使用也能产生问题,因为新版的库里可能包含早先的版本没有的符号和说明。 
(7)
在不同的模块中使用内联和非内联的编译选项能够导致LNK2001错误。如果创建C++库时打开了函数内联(/Ob1/Ob2),但是在描述该函数的相应头文件里却关闭了函数内联(没有inline关键字),只是将得到错误信息。为避免该问题的发生,应该在相应的头文件中用inline关键字标志为内联函数。 
(8)
不正确的/SUBSYSTEMENTRY设置也能导致LNK2001错误。 

19.
如何调试一个没有源码的exe文件调用的dll 
Visual C++ 6.0中,进入“Project Setting”对话框然后选择Debug标签页。通常Visual Studio默认“executable for debug session”为可执行文件名,但可以将他改成任何你想要的程序。甚至可以指定不同的工作目录以及传递参数到你的程序。这个技术常用来调试Dlls、名字空间扩展、COM对象和其他从某些EXE以及从第三方的EXE中调用的plug-in程序。 

20. Visual C++ 6.0
工程中的项目文件都表示什么 
.opt
:工程关于开发环境的参数文件。如工具条位置等信息。 
.aps(AppStudio File)
资源辅助文件,二进制格式,一般不用去管它。 
.clw
ClassWizard信息文件,实际上是INI文件格式,有兴趣可以研究一下。有时候ClassWizard出了问题,手工修改CLW文件可以解决。如果此文件不存在的话,每次用ClassWizard的时候回提示是否重建。 
.dsp(DevelopStudio Project)
:项目文件,文本格式,不过不熟悉的不要手工修改。 
.dsw(DevelopStudio Workspace)
:是工作区文件,其他特点和.dsp差不多。 
.plg
:是编译信息文件,编译时的errorwarning信息文件(实际上是一个html文件),一般用处不大。在单击菜单【Tool】->Option】弹出的对话框里面有个选项可以控制这个文件的生成。 
.hpj(Help Project)
:是生成帮助文件的工程,用microsoft Help Compiler可以处理。 
.mdp(Microsoft DevStudio Project)
:是旧版本的项目文件,如果要打开此文件的话,会提示你是否转换成新的.dsp格式。 
.bsc
:是用于浏览项目信息的,如果用Source Brower的话就必须有这个文件。如果不用这个功能的话,可以在Project Options里面去掉Generate Browse Info File,这样可以加快编译速度。 
.map
是执行文件的映象信息记录文件,除非对系统底层,这个文件一般用不着。 
.pch(Pre-Compiled File)
:是与编译文件,可以加快编译速度,但是文件非常大。 
.pdb(Program Database)
:记录了程序有关的一些数据和调试信息,在调试的时候可能有用。 
.exp
:只有在编译DLL的时候才会生成,记录了DLL文件的一些信息,一般也没有用。 
.ncb
:无编译浏览文件(no compile browser)。当自动完成功能出问题时可以删除此文件。编译工程后会自动生成。 

  


ALT + F10

应用代码更改但不停止调试模式。有关更多信息,请参见编辑并继续

 

调试.自动窗口

CTRL + ALT + VA

显示自动窗口以查看当前过程中在当前执行行范围内的当前变量的值。有关更多信息,请参见中断执行

调试.全部中断

CTRL + ALT + BREAK

临时停止执行调试会话中的所有进程。仅适用于运行模式。

调试.断点

ALT + F9
CTRL + ALT + B

显示新断点对话框,在其中可以添加和修改断点。

调试.调用堆栈

ALT + 7
CTRL + ALT + C

显示调用堆栈窗口,以显示当前执行线程的所有活动过程或堆栈帧的列表。仅适用于运行模式。

调试.清除所有断点

CTRL + SHIFT + F9

清除项目中的所有断点。

调试.反汇编

ALT + 8

显示反汇编窗口

调试.启用断点

CTRL + F9

在当前行上启用断点。

调试.异常

CTRL + ALT + E

显示异常对话框。

调试.即时

CTRL + ALT + I

显示立即窗口,在其中可以计算表达式并执行各个命令。

调试.局部变量

ALT + 4
CTRL + ALT + V
L

显示局部变量窗口以查看当前堆栈帧中每个过程的变量及变量值。

调试.内存1

ALT + 6
CTRL + ALT + M
1

显示内存 1”窗口以查看大缓冲区、字符串和其他在监视变量窗口中没有清楚显示的数据。

调试.内存2

CTRL + ALT + M2

显示内存 2”窗口,查看在监视变量窗口中不能清楚地显示的大缓冲区、字符串和其他数据。

调试.内存3

CTRL + ALT + M3

显示内存 3”窗口,查看在监视变量窗口中不能清楚地显示的大缓冲区、字符串和其他数据。

调试.内存4

CTRL + ALT + M4

显示内存 4”窗口,查看在监视变量窗口中不能清楚地显示的大缓冲区、字符串和其他数据。

调试.模块

CTRL + ALT + U

显示模块窗口,此窗口允许查看程序使用的 .dll .exe 文件。

调试.新断点

CTRL + B

在当前代码行中插入或清除断点。

调试.快速监视

CTRL + ALT + Q
SHIFT + F9

显示包含选定表达式的当前值的快速监视对话框。仅在中断模式中可用。使用该命令可检查尚未为其定义监视表达式的变量、属性或其他表达式的当前值。

调试.寄存器

ALT + 5
CTRL + ALT + G

显示寄存器窗口,此窗口显示用于调试本机代码应用程序的注册内容。

调试.重新启动

CTRL + SHIFT + F5

终止调试会话,重新生成应用程序,然后再从头开始运行该应用程序。适用于中断和运行模式。

调试.运行文档

CTRL + ALT + N

显示运行文档窗口,此窗口显示正在调试的进程中的文档集。适用于运行模式。

调试.运行到光标处

CTRL + F10

在中断模式下,从当前语句继续执行代码,直到选定的语句。当前执行行边距指示器出现在页边距指示器栏中。有关更多信息,请参见运行到光标位置

调试.设置下一语句

CTRL + SHIFT + F10

在选择的代码行上设置执行点。有关更多信息,请参见设置执行点

调试.显示下一语句

ALT + 数字键区中的 *

突出显示要执行的下一条语句。

调试.启动

F5

自动附加调试器,并从 <项目> 属性对话框中指定的启动窗体运行应用程序。如果为中断模式,则更改为继续

调试.开始执行不调试

CTRL + F5

在不调用调试器的情况下运行代码。

调试.逐语句

F11

在执行进入函数调用后,按逐条语句执行代码。有关更多信息,请参见进入并单步执行

调试.跳出

SHIFT + F11

执行当前执行点所处函数的剩余行。有关更多信息,请参见单步执行

调试.逐过程

F10

执行下一行代码,但不继续执行任何函数调用。

调试.停止调试

SHIFT + F5

停止运行程序中的当前应用程序。适用于中断和运行模式。

调试.This

CTRL + ALT + VT

显示“This”窗口,此窗口允许查看与当前方法关联的对象的数据成员。

调试.线程

CTRL + ALT + H

显示线程窗口以查看当前进程的所有线程以及它们的相关信息。

调试.切换断点

F9

在当前行设置或移除断点。

调试.切换反汇编

CTRL + F11

显示当前源文件的反汇编信息。仅在中断模式中可用。

工具.调试进程

CTRL + ALT + P

显示进程对话框,此对话框允许在单个解决方案中同时调试多个程序

 

 

 

 

了解调试,首先要知道"断点"这个概念.断点就是程序运行中可能会中断的地方,方便开发者在程序运行的过程中查看程序当前的运行状态,比如变量的值,函数的返回值等等.究竟怎么使用断点呢?

  1.调试快捷键

  F9——在当前光标所在的行下断点,如果当前行已经有断点,则取消断点.
  F5——调试状态运行程序,程序执行到有断点的地方会停下来.
  F10——单步执行程序.
  F11——F10的区别是,如果当前执行语句是函数调用,则会进入函数里面.
  CTRL+F10——运行到光标所在行.
  SHIFT+F11——跳出当前所在函数.

  特别说明:

  a.有的地方不能下断点.比如空行,基本类型定义语句(不初始化),等等非执行语句.比如

  int           i;                      // 此行不能下断点   字串7
  int           j =0;                  // 这里可以下
  CString       str;                    // 这里可以下
  int           k = Max(i, j);           // 这里可以下

  b.不是所有断点都会().比如下断点的语句在程序里面没有被执行.

  c.此外,ALT+F9还可以下条件断点,不过这个不常用,有兴趣的可以自己研究:)

  2.如何调试Release版的程序?

  有些程序在debug下运行的很好,但在release下却总是失败,默认情况下release是不能调试的.怎么解决呢?

  其实"debug""release"都只是一个代号而已,各自对应一组不同的编译选项.

  在release的默认设置下,ALT+F7 ,调出工程设置对话框,切换到link选项卡,勾选"Generate debuginfo",然后再切换到C/C++选项卡,"Optimizations"里面选"Disable(Debug)",在下面的"Debug info"里面选"Program Databasefor Edit and Continue".然后点OK保存设置,重新编译程序,下断点即可.

  3.上面两点已经能应付很多种情况了,但是有时候即使在debug下也不能下断点,我以前也曾经遇到过这种问题,一个调了4层的dll,就是不能下断点.其实还除了上面的方法,还有一种最底层的实现技术:使用汇编.

  细心的人可能会发现,有时候在调试状态下当程序出现异常的时候,光标会指向汇编代码,而这个代码就是int 3,这其实是一个中断.

  在你的代码的任意地方加上

  __asm{
      int3
  };

  用debug编译,然后直接运行程序.当程序执行到上述代码的时候,就会出现一个框,告诉你说一大堆信息,说程序错了,下面有"调试""终止""忽略",不用理,点调试就可以进入跟 踪了。这种方法我还没有失手过:)

 

原创粉丝点击