Compiler construction 为什么不总是使用编译器优化?

Compiler construction 为什么不总是使用编译器优化?,compiler-construction,compiler-optimization,Compiler Construction,Compiler Optimization,具有未定义的行为,因此编译器优化实际上导致程序中断 但如果代码中没有未定义的行为,那么有没有理由不使用编译器优化?我理解,有时出于调试目的,可能不需要优化的代码(如果我错了,请纠正我)。除此之外,在生产代码上,为什么不总是使用编译器优化呢 此外,是否有理由使用,比如说,-O而不是-O2或-O3?简单。编译器优化错误。刚刚发生在我身上。由for interface Java生成的代码是正确的,但不能与gcc上的-O2一起使用。一个例子是短路布尔求值。比如: if (someFunc() &

具有未定义的行为,因此编译器优化实际上导致程序中断

但如果代码中没有未定义的行为,那么有没有理由不使用编译器优化?我理解,有时出于调试目的,可能不需要优化的代码(如果我错了,请纠正我)。除此之外,在生产代码上,为什么不总是使用编译器优化呢


此外,是否有理由使用,比如说,
-O
而不是
-O2
-O3

简单。编译器优化错误。

刚刚发生在我身上。由for interface Java生成的代码是正确的,但不能与gcc上的-O2一起使用。

一个例子是短路布尔求值。比如:

if (someFunc() && otherFunc()) {
  ...
}

“智能”编译器可能会意识到someFunc由于某种原因总是返回false,使整个语句的计算结果为false,并决定不调用otherFunc以节省CPU时间。但是,如果otherFunc包含一些直接影响程序执行的代码(可能会重置全局标志或其他内容),它现在将不会执行该步骤,并且程序将进入未知状态。

编译器优化有两个缺点:

  • 优化几乎总是会重新排列和/或删除代码。这将降低调试器的效率,因为在源代码和生成的代码之间不再存在1:1的对应关系。堆栈的某些部分可能丢失,单步执行指令可能会以违反直觉的方式跳过部分代码
  • 优化通常执行起来很昂贵,因此在启用优化的情况下编译代码所需的时间要比不启用优化的情况下长。在编译代码时,很难做任何有效率的事情,因此缩短编译时间显然是一件好事
  • -O3执行的一些优化可能会导致更大的可执行文件。在某些生产代码中,这可能是不可取的

    不使用优化的另一个原因是,您正在使用的编译器可能包含仅在执行优化时存在的错误。不进行优化的编译可以避免这些错误。如果您的编译器确实包含bug,那么更好的选择可能是报告/修复这些bug,更改为更好的编译器,或者编写完全避免这些bug的代码


    如果您希望能够对发布的生产代码执行调试,那么最好不要优化代码。

    如果没有未定义的行为,但存在明确的破坏行为(确定性正常错误或不确定的竞争条件),关闭优化是值得的,这样您就可以使用调试器逐步完成代码。

    通常,当我达到这种状态时,我喜欢做以下组合:

  • 调试构建(无优化)并逐步完成代码
  • 向stderr添加了大量诊断语句,以便我可以轻松跟踪运行路径
  • 如果错误更狡猾,我会拉出valgrinddrd,并根据需要添加单元测试,以隔离问题并确保在发现问题时,解决方案按预期工作

    在极少数情况下,调试代码可以工作,但发布代码失败。当这种情况发生时,问题几乎总是在我的代码中;发布版本中的积极优化可能会揭示由错误理解临时版本的生命周期等引起的错误。。。但即使在这种情况下,调试构建也有助于隔离问题

    简言之,专业开发人员构建和测试调试(非优化)和发布(优化)二进制文件有一些很好的理由。总之,让调试版本和发布版本始终通过单元测试将节省大量调试时间。

    3个原因
  • 它有时会混淆调试器
  • 它与某些代码模式不兼容
  • 不值得这样做:速度慢或者有问题,或者占用太多内存,或者生成的代码太大
  • 在案例2中,想象一些故意更改指针类型的操作系统代码。优化器可以假设无法引用错误类型的对象,并生成代码,该代码在寄存器中为更改的内存值添加别名,并获得“错误”1答案

    案例3是一个有趣的问题。有时优化器会使代码变小,但有时会使代码变大。大多数程序都不受CPU的限制,即使是受CPU限制的程序,实际上只有10%或更少的代码是计算密集型的。如果优化器有任何缺点,那么它只是一个不到10%的程序的胜利

    如果生成的代码更大,那么缓存友好性就会降低。对于一个在小循环中使用O(n3)算法的矩阵代数库来说,这可能是值得的。但是对于具有更典型时间复杂性的程序,溢出缓存实际上可能会使程序变慢。优化器通常可以针对所有这些内容进行调优,但是如果程序是一个web应用程序,比如说,如果编译器只做通用的事情,并且允许开发人员不打开花哨的技巧,那么肯定会对开发人员更友好



    一,。此类程序通常不符合标准,因此优化器在技术上是“正确的”,但仍然没有达到开发人员的预期。

    原因是您开发一个应用程序(调试版本),而您的客户运行完全不同的应用程序(发布版本)。如果测试资源不足和/或使用的编译器不是很流行,我将禁用对发布版本的优化


    MS发布了许多针对MSVC x86编译器中优化错误的修补程序。幸运的是,我在现实生活中从未遇到过。但其他编译器并非如此。SMS编译器在MS嵌入式Visual C++中是非常错误的。

    < P>我看到的两个大的原因
    #include <stdio.h>
    
    int puts(const char *str) {
        fputs("Hello, world!\n", stdout);
        return 1;
    }
    
    int main() {
        printf("Goodbye!\n");
        return 0;
    }