• 1. 第4章 Visual C++调试技术在开发程序的过程中,经常需要查找程序中的错误,程序调试是一项复杂而苦恼的工作,它需要程序员具有足够的耐性。程序中的一个小错误可能会花费大量的时间才能发现和解决,这就需要利用调试工具来帮助开发者进行程序的调试。Visual C++中集成了功能强大的调试工具,提供多种调试方案,可以帮助程序员更加有效地调试程序。本章将对Visual C++中的调试工具和技术作详细介绍。
  • 2. 4.1 Debug与Release当编译应用程序时,开发者可以选择两种目标之一:Debug和Release。Debug通常称为调试版本,它包含调试信息,并且不作任何优化,便于程序员调试程序。Release称为发布版本,它往往是进行了各种优化,使得程序在代码大小和运行速度上都是最优的,以便用户很好地使用。
  • 3. 4.2 调试的过程调试实际上就是在程序运行过程的某一阶段观测程序的状态,而在一般情况下程序是连续运行的,所以必须使程序在某一地点停下来。所以开发者所做的第一项工作就是设立断点。其次,再运行程序,让程序在设置的断点处停下来,再利用各种工具观察程序的状态。下面将按照这个思路,来介绍程序调试的过程。
  • 4. 4.2.1 设置断点断点是调试器设置的一个代码位置。当程序运行到断点时,程序中断执行,回到调试器。断点提供了一种强大的工具,使开发者能够在需要的时间和位置挂起执行。与逐句或逐条指令地检查代码不同的是,可以让程序一直执行,直到遇到断点,然后开始调试。这大大地加快了调试过程。没有这个功能,调试大的程序几乎是不可能的。在程序中设置断点的方法有以下几种。
  • 5. 4.2.2 控制程序的运行前面讲述了如何设置断点,下面来介绍如何利用断点控制程序的运行。Visual C++允许正在调试的程序继续运行、单步运行、运行到当前光标处。
  • 6. 4.3 使用查看工具 调试过程中,开发人员要想找出程序的错误之处,必须能够观察程序在运行过程中的状态。程序状态主要包括各变量的值、寄存中的值、内存中的值、堆栈中的值。Visual C++提供了许多工具来帮助开发人员查看程序的状态。经常使用的工具有观察窗口(Watch)、快速查看窗口(Quick watch)、变量窗口(Variables)、寄存器窗口(Register)、内存窗口(Memory)、调用栈窗口(Call stack)等。本节将对这些常用的工具作详细介绍。
  • 7. 4.3.1 弹出式调试信息泡泡当程序在断点停下来后,要观察一个变量或表达式的值时,最容易的方法是利用调试信息泡泡(Data Tips Pop_up Information)。要看一个变量的值,只要将鼠标放到该变量上,就会看到一个信息泡泡弹出,显示出该变量的值,如图所示。
  • 8. 4.3.2 变量窗口在Visual C++中,执行【View】|【Debug Windows】|【Variables】命令,变量窗口(Variable Window)将会出现在屏幕上,如图所示。Name一栏显示变量名称,Value一栏显示变量对应的值。在变量窗口的下部有3个选项卡:Auto、Locals、this。选择不同的选项卡,不同类型的变量将会在该窗口中显示。
  • 9. 4.3.3 观察窗口在Visual C++中,执行【View】|【Debug Windows】|【Watch】命令,观察窗口(Watch Window)将会出现在屏幕上,如图4.14所示。在观察窗口中双击Name栏的某一空行,输入要查看的变量名或表达式然后回车,将会在Value栏中看到该变量或表达式的值。随着程序的逐步执行,将显示该变量或表达式值的变化。
  • 10. 4.3.4 快速查看窗口在Visual C++中,执行【Debug】|【QuickWatch】命令,快速查看窗口(Quick Watch)将会出现在屏幕上,如图4.15所示。
  • 11. 4.3.5 内存查看窗口在Visual C++中,除了可以查看变量和表达式的值,还可以查看内存中的值。
  • 12. 4.3.6 寄存器窗口在调试过程中,有时需要查看或修改寄存器中的值。Visual C++提供了寄存器窗口来完成这项工作。
  • 13. 4.3.7 调用堆栈窗口首先读者应该了解什么是调用堆栈。假设有这样几个函数,分别是function1()、function2()、function3(),且function1()调用function2(),function2()调用function3()。在function3()运行过程中,可以从当前堆栈中了解到调用它的那几个函数分别是谁。把函数的顺序关系看做为function3()、function2()、function1(),这样呈现出一种“堆栈”的特性,最后被调用的函数位于最上方,因此称这种关系为调用堆栈。
  • 14. 4.4 其他调试技术前面已经讲述了常规的调试方法及常用调试工具的使用,这些调试工具通常在其他编程环境中也有。除此之外Visual C++还提供了一些特有的、更高级的调试工具。在后边的章节中读者会了解到,在利用Visual C++开发的过程中,使用MFC(Microsoft Foundation Classes)将会极大地方便应用程序的开发,这是Visual C++最重要的特点。基于这个原因Microsoft公司在MFC中提供了一些特性来帮助开发者进行程序的调试,本节将对这些工具做详细的介绍。
  • 15. 4.4.1 TRACE宏TRACE宏对于在Visual C++下调试程序来说是很有用的东西,它有点类似C语言中的printf()函数,使程序在开发过程中输出一些调试信息,以让开发者了解程序的某些状态。TRACE宏把结果输出到调试窗口,注意,TRACE宏只有在Debug版本下才有效,在Release版本中,它将被忽略。
  • 16. 4.4.2 ASSERT宏ASSERT宏在调试程序过程中也经常用到,使用它可以对某一条件进行判定,如果条件为真,程序将继续执行,如果条件为假,系统将弹出一个警告对话框,并终止运行。ASSERT宏主要用来判断程序中是否出现了明显的非法数据,如果出现了,将会终止程序运行以免导致严重后果,同时也便于查找错误。
  • 17. 4.4.3 VERIFY宏VERIFY宏的功能与ASSERT类似,所不同的是,在Release版本中,ASSERT不计算输入的表达式的值,而VERIFY会计算表达式的值。如果必须计算此表达式的值,则用VERIFY代替ASSERT。
  • 18. 4.5 小结本章介绍了在Visual C++环境下,如何调试程序及Visual C++中的各种调试工具的使用。通过本章的学习读者应对Visual C++环境有了更深入的了解,可以利用多种调试工具调试程序。Visual C++虽然提供了强大的调试工具,但一个好的程序员不应该把所有的判断交给编译器和调试器,而是应该在程序中自己加以程序保护和错误定位。