偶尔进行某些级别的优化时,C ++代码将无法工作。可能是编译器进行了优化而破坏了代码,也可能是包含未定义行为的代码,这些行为使编译器可以做任何感觉。
假设我有一些仅在使用更高的优化级别进行编译时会中断的代码。我怎么知道是代码还是编译器,如果是编译器怎么办?
偶尔进行某些级别的优化时,C ++代码将无法工作。可能是编译器进行了优化而破坏了代码,也可能是包含未定义行为的代码,这些行为使编译器可以做任何感觉。
假设我有一些仅在使用更高的优化级别进行编译时会中断的代码。我怎么知道是代码还是编译器,如果是编译器怎么办?
Answers:
我可以肯定地说,在大多数情况下,损坏的是您的代码而不是编译器。即使是在非常特殊的情况下(当它是编译器时),您也可能会以一种不寻常的方式使用一些晦涩的语言功能,而这些特性并未为特定的编译器做好准备;换句话说,您很可能会将代码更改为更惯用的语言,从而避免了编译器的薄弱环节。
无论如何,如果可以证明发现了编译器错误(基于语言规范),请向编译器开发人员报告该错误,以便他们可以在某个时间对其进行修复。
和其他错误一样,请执行一个受控实验。缩小可疑区域的范围,关闭其他所有功能的优化,然后开始更改应用于该代码块的优化。一旦获得100%的可重复性,就开始更改代码,引入可能破坏某些优化的内容(例如,引入可能的指针别名,插入可能产生副作用的外部调用等)。在调试器中查看汇编代码也可能会有所帮助。
检查产生的汇编代码,并查看其是否满足您的源代码的要求。请记住,以某种非显而易见的方式,确实是您的代码有过错的可能性很高。
在30多年的编程过程中,我发现的真正的编译器(代码生成)错误的数量仍然仅为〜10。在同一时期内发现并修复的我自己的(以及其他人的)错误的数量可能是> 10,000。我的“经验法则”是,任何给定的错误是由编译器引起的,概率小于0.001。
int + int
溢出的代码,就像编译成硬件ADD指令一样。使用旧版本的GCC编译时,效果很好,但使用较新的编译器编译时,效果不佳。显然,GCC的好心人决定,由于整数溢出的结果是不确定的,因此他们的优化器可以在假设它永远不会发生的情况下运行。它根据代码优化了一个重要的分支。
如果您想知道它是代码还是编译器,则必须完全了解C ++的规范。
如果仍然存在疑问,则必须完全了解x86程序集。
如果您不打算同时学习两个方面的知识,那么编译器根据优化级别做出不同的解析几乎可以肯定是一种不确定的行为。
比优化器错误更容易在标准代码上遇到编译错误或内部编译错误。但是我听说编译器错误地优化了循环,忘记了方法引起的一些副作用。
我对如何知道它是您还是编译器没有任何建议。您可以尝试其他编译器。
有一天,我想知道是否是我的代码,有人向我建议了valgrind。我花了5到10分钟来用它运行程序(我认为valgrind --leak-check=yes myprog arg1 arg2
确实有,但是我使用了其他选项),它立即向我显示了在一种特定情况下出现问题的一行。自那时以来,我的应用一直运行平稳,没有出现奇怪的崩溃,错误或奇怪的行为。valgrind或其他类似工具是了解您的代码是否正确的好方法。
旁注:我曾经想知道为什么我的应用程序的性能糟透了。事实证明,我所有的性能问题也都在同一行。我写了for(int i=0; i<strlen(sz); ++i) {
。sz是几MB。出于某种原因,即使在优化之后,编译器也每次都运行不畅。一条线可能很重要。从表演到崩溃
越来越普遍的情况是,编译器破坏了为C语言的方言编写的代码,这些代码支持标准未规定的行为,并允许针对这些方言的代码比严格符合标准的代码更有效。在这种情况下,将“破损”代码描述为在实现目标方言的编译器上100%可靠的代码,或者将处理不支持所需语义的方言的编译器描述为“破损”是不公平的。 。相反,问题仅源于以下事实:启用了优化的现代编译器处理的语言与曾经流行的方言有所不同(并且许多禁用了优化甚至甚至启用了优化的编译器仍在处理该方言)。
例如,为方言编写了许多代码,这些方言将gcc解释的标准未规定的许多指针别名模式识别为合法,并利用这些模式使代码的直接翻译更加可读和高效。比gcc对C标准的解释要高。此类代码可能与gcc不兼容,但这并不意味着它已损坏。它仅依赖于gcc仅在禁用优化的情况下支持的扩展。
隔离问题点,并将观察到的行为与根据语言规范应发生的行为进行比较。绝对不容易,但这就是您必须了解的(而不仅仅是假设)。
我可能不会那么细致。相反,我会问编译器制造商的支持论坛/邮件列表。如果确实是编译器中的错误,那么他们可能会修复它。无论如何,可能是我的代码。例如,关于线程中的内存可见性的语言规范可能会很违反直觉,并且只有在某些特定的硬件(!)上使用某些特定的优化标志时,它们才会变得明显。规范可能无法定义某些行为,因此它可以与某些编译器/某些标志一起使用,而不能与其他某些一起使用,等等。