【发布时间】:2011-01-19 05:56:46
【问题描述】:
为什么在调试应用程序时需要/建议关闭所有编译器优化?
背景
我在一个 8 位微控制器 (OKI 411) 中工作,它有 15K 可用代码存储空间用于中断服务例程 + ROM 区域/窗口(常量全局变量)+ 代码。我们几乎吃光了大约 13K,因此在调试期间打开最大可能的优化是非常诱人的。
【问题讨论】:
标签: compiler-construction microcontroller compiler-optimization
为什么在调试应用程序时需要/建议关闭所有编译器优化?
背景
我在一个 8 位微控制器 (OKI 411) 中工作,它有 15K 可用代码存储空间用于中断服务例程 + ROM 区域/窗口(常量全局变量)+ 代码。我们几乎吃光了大约 13K,因此在调试期间打开最大可能的优化是非常诱人的。
【问题讨论】:
标签: compiler-construction microcontroller compiler-optimization
在编译调试二进制文件时,编译器会尝试在代码语句(或代码语句片段)与汇编语言指令之间保持 1:1 的对应关系。这样,当您进行调试时,您可以逐条指令进行单步调试,并且调试器很容易将其在二进制文件中的当前位置与正确的源代码相关联。通常编译器还会确保所有命名变量确实存在于内存中的某个位置,以便您可以在调试器中查看它们的内容。
编译器优化可能会省略未使用或不必要的局部变量,并且可能会重组您的代码以提高效率。函数可以内联,表达式可以部分或全部预先计算或重新排列。大多数这些和类似的优化使原始源代码与生成的程序集相关联变得困难。
【讨论】:
考虑:
for (i = 0; i < 10; i++) {
src[i] = dest[i];
}
优化后的代码如下:
src[0] = dest[0];
src[1] = dest[1];
⋮
src[9] = dest[9];
换句话说,不再有i。调试器希望i 在堆栈帧上,但优化器将其删除。
此外,当单步执行时,PC 会到处乱跳(显然是随机的),并且您会遇到其他各种奇怪的情况,这会使调试变得非常困难或不可能(取决于优化器所做的)。
【讨论】:
打开它就可以了。它通常是关闭的,因为它使编译速度更快,这对于大型项目来说可能是一个真正的问题。如果可以的话,实际上最好打开它,这样你就不会因为最后一分钟的优化而遇到任何令人讨厌的问题。
在你的情况下,我肯定会打开它。
这可能会导致某些形式的调试出现问题,但在这些情况下您应该能够将其关闭。
【讨论】:
我遇到了类似的情况,我试图从硬件寄存器中读取,该寄存器是内存映射的,它在 gcc 中使用 CFLAGS="-o2" 给了我错误的值。但是当我打开 CFLAGS= “-O0”,它开始工作了。值得一提的是,通过将其转换为 volatile 变量可以实现相同的结果,从而绕过编译器优化。
【讨论】:
我唯一能想到的就是它可能会使调试变得更加困难。
除此之外,应该没有问题。
【讨论】: