c++ - 哪些优化编译器开关使调试变得非常困难?

标签 c++ visual-c++ visual-studio-2015 compiler-optimization

我遇到了一个根本没有 PDB 的调试情况(不幸的是,这种情况仍然会发生)。在特定情况下,我正在研究堆栈损坏,并尝试进行手动堆栈遍历。但是,ESP 和 EBP 寄存器之间存在严重的不匹配,因此我认为代码是在启用了 /Oy 优化(帧指针省略)的情况下编译的。在这种情况下,我不得不放弃。

我现在的问题是:对于优化的 Visual Studio 2015 C++ 编译器开关,哪些会使调试变得困难?一个简短的解释为什么它会变硬会很好。

为了限制问题的范围,答案应仅考虑 x86(32 位)。

可用选项可以是found on MSDN ,因为有:

  • O1 - 创建小代码
  • Os - 喜欢小代码
  • O2 - 创建快速代码
  • Ot - 喜欢快速代码
  • Ob - 控制内联扩展
  • Oi - 生成内部函数

以下不需要考虑:

  • Od - 禁用优化。这显然会造成最少的麻烦
  • Og - 已弃用
  • Ox - 只是其他元素的组合。这显然会造成各个开关的麻烦的总和
  • Oy - 省略帧指针。我已经知道了。这让堆栈行走变得非常困难。这与猜测有关。

最佳答案

哇,有很多不同类型的代码优化,比我了解的要多得多,但我会尝试详细说明会显着影响调试体验的不同优化,优化的知识可以帮助指导编译器开关将启用它。

  • 重新排序指令以防止 cpu 空转,通常会产生更多的代码,调试器会出现在代码周围跳跃而不是线性执行。
  • 将代码缩减为编译时间常数,更小的代码和更快的代码,调试时将跳过这段代码。
  • 省略帧指针,生成更小的代码,但更难遍历堆栈。
  • 有效的寄存器使用,这将导致变量在超出范围之前不可读或出错,因为编译器已经决定变量可以安全地提前退出并且它的寄存器被释放用于其他地方,而不是不必要地将它的值推送到堆栈。这会生成更小、更快的代码。
  • 内联,内联产生更胖的代码更快,内联函数不会出现在调用堆栈中。

这些天所有的优化标志都不受欢迎,Profile Guided Optimization 是迄今为止在发布中使用优化的首选方式,如果你想调试发布式代码,你应该使用 -Zo 标志,它会产生更好的 pdb's可以获得有关寄存器中的内联函数和变量的更多信息。

GCC 和 clang 有一个针对每个优化的标志集 -O 标志只是这些标志的合并,查看 GCC 如何分配优化和每个优化的详细信息将有助于进一步了解所有不同的优化编译器,在将军,做。

编辑:此外,如果您想打开各个编译器标志并查看它对 GCC 和 clang 编译代码的作用,god bolt 真的很有用 https://gcc.godbolt.org

关于c++ - 哪些优化编译器开关使调试变得非常困难?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40781403/

相关文章:

c++ - 使用 C++ Builder 时 VC++ Dll 无法在 Windows XP Sp3 上运行

c - 需要帮助来删除和编辑库存中的项目

c++ - 如何为具有类型删除数据成员的类实现复制构造函数?

C++ - 开发自己的 std::count_if 版本

c++ - 为什么我的直播摄像头在使用 OpenCV+Qt 时严重滞后

c++ - 局部常量变量不是 constexpr 可评估的,但无法弄清楚为什么

c++ - 如何在 Visual Studio 2015 中分析 "external"DLL 代码

visual-studio-2015 - 无法将自动化测试与测试用例相关联

asp.net-core - VS 2015 在哪里获取 KRE 版本?

c++ - 为什么代码块中的一些词如 "copy"和 "insert"显示为绿色?