为什么在调试应用程序时必须/建议关闭所有编译器优化?
背景
我正在使用一个8位微控制器(OKI 411),它具有15K可用代码存储空间,用于中断服务程序+ ROM区域/窗口(const全局变量)+代码。我们差不多吃掉了大约13K,所以在调试过程中打开最大可能的优化非常诱人。
答案 0 :(得分:6)
编译调试二进制文件时,编译器会尝试在代码语句(或代码语句)与汇编语言指令之间保持1:1的对应关系。这样,当您进行调试时,您可以逐步执行指令,并且调试器可以轻松地将其在二进制文件中的当前位置与正确的源代码相关联。通常,编译器还确保所有命名变量实际存在于内存中的某个位置,以便您可以在调试器中查看它们的内容。
编译器优化可能会忽略未使用或不必要的局部变量,并可能重新构建代码,以使其更有效。可以内联函数,并且可以部分或全部预先计算或重新排列表达式。大多数这些和类似的优化使得很难将原始源代码与生成的程序集相关联。
答案 1 :(得分:5)
考虑一下:
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会在整个地方跳跃(显然是随机的),你会遇到各种其他奇怪的东西,这会使调试变得非常困难或不可能(取决于优化器的作用)。
答案 2 :(得分:2)
打开它可以。它通常是关闭的,因为它使编译更快,对于大型项目来说可能是一个真正的问题。如果可以的话,最好将它打开,这样你就不会因为最后一分钟的优化而遇到任何令人讨厌的问题。
在你的情况下,我肯定会打开它。
这可能会导致某些形式的调试出现问题,但在这种情况下您应该可以将其关闭。
答案 3 :(得分:2)
我遇到了类似的情况,我试图从硬件寄存器读取,寄存器是内存映射的,它在gcc中给了我错误的值CFLAGS =“ - o2”。但是当我转向CFLAGS = “-O0”,它开始工作。可能值得一提的是,通过将其转换为volatile变量可以实现相同的结果,因此绕过了编译器优化。
答案 4 :(得分:1)
我唯一能想到的是它可能会使调试变得更加困难。
除此之外,应该没有问题。