本文介绍需要设置哪些编译器选项来更好地调试优化后的代码。
从 Visual Studio 2022 版本 17.14 开始,可以使用更好的体验来调试优化代码,就像它是未优化编译一样,同时保持优化代码的速度。 有关详细信息,请参阅 C++动态调试(预览版)。
注释
你看到的对话框和菜单命令可能与“帮助”中所述的命令不同,具体取决于你的活动设置或版本。 若要更改设置,请选择 “工具”菜单上的“导入和导出设置”。 有关详细信息,请参阅重置所有设置。
注释
/Zo(增强优化调试) 编译器选项(Visual Studio Update 3 中引入)为优化代码(未使用 /Od 编译器选项生成的项目)生成更丰富的调试信息。 请参阅 /O 选项(优化代码))。 这包括对调试局部变量和内联函数的改进支持。
当使用 /Zo 编译器选项时,编辑并继续会被禁用。
当编译器优化代码时,它会重新定位并重新组织指令。 这会导致更高效的编译代码。 由于这种重新排列,调试器不能始终标识与一组指令相对应的源代码。
优化可能会影响:
优化器可以删除局部变量,或将其移动到调试器无法理解的位置。
函数内的位置,当优化器合并代码块时,这些位置会被更改。
调用堆栈上框架的函数名称(如果优化器合并两个函数,则函数名称可能是错误的)。
但是,假定所有框架都有符号,则在调用堆栈上看到的框架几乎总是正确的。 如果堆栈损坏,如果有用汇编语言编写的函数,或者调用堆栈上存在没有匹配符号的操作系统帧,则调用堆栈上的帧可能会错误。
全局变量和静态变量始终正确显示。 结构布局也是如此。 如果你有指向结构的指针且指针的值正确,则结构的每个成员变量将显示正确的值。
由于这些限制,应尽可能使用程序未优化的版本进行调试。 默认情况下,优化在C++程序的调试配置中处于关闭状态,并在“发布”配置中打开。
但是,bug 可能仅出现在程序的优化版本中。 在这种情况下,必须调试优化的代码。
在“Debug”生成配置中打开优化
创建新项目时,选择
Win32 Debug
目标。 接下来要一直使用Win32 Debug
目标,直至程序已进行全面调试并可以生成Win32 Release
目标为止。 编译器不会优化Win32 Debug
目标。在解决方案资源管理器中选择项目。
在“视图”菜单上,单击“属性页”。
在“属性页”对话框中,确保在 配置 下拉列表中选择
Debug
。在左侧的文件夹视图中,选择 C/C++ 文件夹。
在 C++ 文件夹下,选择
Optimization
。在右侧的属性列表中,找到
Optimization
。 它旁边的设置可能显示为Disabled (
/Od)
。 选择其他选项之一(Minimum Size``(
/O1)
、Maximum Speed``(
/O2)
、Full Optimization``(
/Ox)
或Custom
)。如果选择
Optimization
的Custom
选项,现在可以为属性列表中显示的任何其他属性设置选项。选择项目属性页的配置属性、C/C++、命令行节点,并将
(
/Zo)
添加到 其他选项 文本框中。警告
添加
/Zo
会禁用编辑并继续。调试优化代码时,请使用 反汇编 窗口查看创建和执行的说明。 设置断点时,需要知道断点可能与指令一起移动。 例如,请考虑以下代码:
for (x=0; x<10; x++)
假定在该行设置了一个断点。 你可能希望断点命中 10 次,但如果代码已优化,则断点只命中一次。 这是因为第一个指令将 x
的值设置为 0。 编译器认识到,这只需完成一次,并将其移出循环。 断点随之移动。 比较和递增 x
的指令仍保留在循环中。 查看“反汇编”窗口时,单步执行单元自动设置为“指令”以增强控制,这在逐句通过优化的代码时很有用。