wenmo8 发布的文章

当处于调试状态时,"调试"--->"窗口"---->"模块"

右击**“模块”窗口并选择“符号加载信息”后,将打开“符号加载信息”**对话框。

  • 信息
    根据 Visual Studio 安装设置和在**“选项”**对话框中对符号设置所做的更改,显示搜索符号文件(PDB 文件)的目录。

  • 符号设置
    单击此按钮可更改在**“选项”对话框(“调试”类别,“符号”**页)中的符号设置。 在该页上,您可以添加或移除符号位置、指定本地缓存位置(如果使用符号服务器)并控制何时搜索符号位置。

     

     

     

“编辑并继续”处理大多数类型的代码更改。 但是,在程序执行期间,某些更改无法应用。 若要应用这些更改,必须停止执行并生成新版本的代码。

不支持的方案

在以下调试方案中,“编辑并继续”不可用:

  • 在 Windows 98 上调试。

  • 混合模式(本机/托管)调试。

  • SQL 调试。

  • 调试 Dr. Watson 转储。

  • 在未选择**“在未经处理的异常上展开调用堆栈”**选项的情况下,在发生未经处理的异常之后编辑代码。

  • 使用**“附加到”来调试应用程序,而不是单击“调试”菜单上的“开始”**来运行应用程序。

  • 调试优化后的代码。

  • 当目标为 64 位应用程序时,调试托管代码。 如果希望使用“编辑并继续”,必须将目标平台设置为 x86 (**“项目属性”对话框->“编译”选项卡->“高级编译器”**设置。)

  • 如果由于生成错误无法生成新版本的代码,则对旧版本的代码进行调试。

在调试会话期间不能应用的 C/C++ 更改

  • 大多数的全局或静态数据的更改。

  • 从其他计算机复制并且未在本地生成的可执行文件的更改。

  • 影响一个对象(如类的数据成员)布局的数据类型的更改。

  • 添加超过 64k 字节的新代码或数据。

  • 添加要求在指令指针前存在构造函数的变量。

  • 影响需要运行时初始化的代码的更改。

  • 在某些实例中,添加异常处理程序。

  • 资源文件的更改。

  • 只读文件中的代码更改。

  • 没有相应 PDB 文件的代码的更改。

  • 没有对象文件的代码的更改。

如果进行了上面某项更改,然后尝试应用代码更改,**“输出”**窗口中就会出现错误或警告信息。

  • “编辑并继续”不更新静态库。 如果您更改了静态库,仍会继续执行老版本,且不显示任何警告。

链接限制

“编辑并继续”有两种类型的链接器限制:

  • 默认情况下,“编辑并继续”在调试会话结束时重新链接到程序,以创建最新的可执行文件。 自动重新链接方面有一些限制。

  • 有些链接器选项禁用“编辑并继续”。

预编译头限制

默认情况下,“编辑并继续”在后台加载并处理预编译头,以加速对代码更改的处理。 加载预编译头需要分配物理内存,如果您正在一台 RAM 有限的计算机上进行编译,这可能会是一个问题。 在 Windows NT 或 Windows 2000 下,可以使用 Windows NT 任务管理器确定调试时可用的物理内存量,从而确定这是否会成为问题。 如果此数量大于预编译头的大小,则“编辑并继续”应没有问题。 如果此数量小于预编译头的大小,可以禁止“编辑并继续”在后台加载预编译头。

对“编辑并继续”禁用预编译头的后台加载

  1. 在“工具”菜单上,单击“选项”。

  2. 在“选项”对话框中选择“调试”节点,然后选择“编辑并继续”组。

  3. 清除“允许预编译”复选框。

  4. 单击“确定”。

特性限制

“编辑并继续”不重新生成接口定义 (IDL) 文件。 因此,调试时不反映对 IDL 特性的更改。 若要查看对 IDL 特性更改的结果,必须停止调试并重新生成应用程序。 如果 IDL 特性已更改,“编辑并继续”不生成错误或警告。

 

毫无疑问,软件开发人员编写的代码并不总是按照预期行事。 有时它执行一些完全不同的操作! 发生这种情况时,下一个任务是找出原因。尽管我们可能会一直盯着代码看几个小时,但使用调试工具或调试程序会更轻松且更高效。

遗憾的是,调试程序无法神奇地揭示代码中的所有问题或“bug”。 调试意味着在 Visual Studio 等调试工具中逐步运行代码,以找到导致编程错误的确切位置 。 那么就可以了解代码中所需的更正,并且调试工具通常允许进行临时更改,以便可以继续运行该程序。

有效地使用调试程序也是一项需要时间和实践来学习的技能,但从根本上来说这是每个软件开发人员的一项基本任务。 本文随后将介绍调试的核心原则并提供入门提示。

通过问自己正确的问题来澄清问题

在尝试修复之前,这有助于阐明遇到的问题。 我们预计代码已出现了问题,否则你不会试图弄清楚对其进行调试的方法! 因此,开始调试之前,请确保你已确定要解决的问题:

  • 期望代码可执行哪些操作?

  • 相反,发生了什么?

    如果运行应用时遇到了错误(异常),这可能是一件好事! 异常是运行代码时遇到的意外事件,通常是某种错误。 调试工具有助于找到代码中发生异常的确切位置并且帮助调查可能的修复方法。

    如果发生了其他情况,问题的症状是什么? 是否已经怀疑代码中出现此问题的位置? 例如,如果代码显示了某些文本,但文本不正确,则你知道数据已损坏或设置显示文本的代码存在某种 bug。 通过逐步调试调试程序中的代码,可以检查变量的每个更改,以准确地发现分配时间以及分配不正确值的方式。

检查假设

在调查 bug 或错误之前,请考虑你期望获得某个结果的假设。 即使正在查看调试程序中问题的成因,隐藏或未知的假设也可能妨碍识别问题。 可能有一长串可能的假设! 以下是要询问的一些问题,以质疑你的假设。

  • 是否使用正确的 API(即正确的对象、函数、方法或属性)? 正在使用的 API 可能无法按照你的想法执行操作。 (在调试程序中检查 API 调用之后,解决此问题可能需要转至文档以帮助识别正确的 API。)

  • 是否正确地使用了 API? 也许使用了正确的 API,但方法不正确。

  • 代码是否包含任何拼写错误? 很难发现某些拼写错误(例如变量名的简单拼写错误),尤其是在使用不需要在使用变量之前声明变量的语言时。

  • 是否对代码进行了更改,并假设它与所看到的问题无关?

  • 是否期望对象或变量包含与实际情况不同的特定值(或某种类型的值)?

  • 是否知道代码的含义? 调试其他人的代码通常更加困难。 如果不是你的代码,则可能需要花时间准确地了解代码的作用,然后才能有效地进行调试。

    提示

    编写代码时,从小型代码开始,从有效的代码开始! (优秀的示例代码在此处很有用。)有时,通过从演示尝试实现的核心任务的一小段代码开始,可以更轻松地修复大型或复杂的代码集。 然后,可以以增量方式来修改或添加代码,从而在每个点测试错误。