当编译器优化代码时,优化的范围是什么?可以优化了
a)跨越一组嵌套的括号?
b)跨越多个功能?
c)跨度超过文件?
我们正在追逐一个似乎来自优化的模糊错误。代码在发布模式下崩溃但不在调试模式下崩溃。当然,我们知道这可能是堆腐败或其他内存问题bur已经追了一段时间了。我们正在考虑的一个途径是在调试模式下有选择地编译我们的文件,直到问题消失。换句话说:
a)从发布模式下编译的所有文件开始 b)在调试模式下编译1/2文件 如果仍然看到崩溃,请将一半的发布编译文件并在调试模式下编译 如果没有看到崩溃,请说一半在调试模式下编译的文件并在发布模式下编译 重复,直到我们缩小可疑文件为止 这是一个二进制搜索,以缩小问题文件
我们知道如果这是一个内存问题,那么简单地进行这种混合编译可能会使错误消失,但如果我们可以缩小问题文件的范围,我们就会很好。
但是,一个悬而未决的问题是优化的范围是什么 - 它们是否可以跨越多个文件?
答案 0 :(得分:5)
只要不改变语言定义的行为的语义,优化就可以完全任何。这意味着你的第一个问题(a),(b)和(c)的答案都是肯定的。在实践中,大多数编译器并不那么雄心勃勃,但肯定有一些例子。 Clang和LLVM具有link time optimization的标志,允许优化跨越整个程序。 MSVC具有类似的/GL
标志,允许整个程序优化。
这些失败的原因往往是未初始化的变量。静态分析工具可以非常有助于找到您所描述的问题。我不确定你通过优化进行的二进制搜索是否会帮助你追踪太多,尽管有可能。您的错误可能是模块之间相当复杂的交互的结果。
祝你好运!答案 1 :(得分:1)
您可以在发布模式下从崩溃的调用跟踪中大致识别问题文件。然后尝试在没有优化的情况下重建它们 - 这比二进制搜索简单得多。
答案 2 :(得分:0)
要了解编译器优化,一个简单的资源可能是维基百科。它简要地解释了几乎所有现代编译器的一些重要且广泛实现的优化。
也许,您想首先阅读wiki条目,尤其是以下部分:
答案 3 :(得分:0)
我认为你问的是错误的问题。
不太可能(除非你做一些特别的事情)优化器是你的问题。
问题很可能是代码中未初始化的变量 当你在调试模式下编译时,大多数编译器会将所有内存初始化为特定的模式,这样在调试过程中你可以看到内存发生了什么(它是分配的/它是否已经去除/是它来自堆栈/是堆栈从等等回来。)
因此,在调试模式下,任何未初始化的内存都具有可由调试器识别的特定模式。确切的模式取决于编译器。但这可以使草率代码工作,因为未初始化的指针是NULL,整数计数器从0开始等。
编译释放模式时,所有额外的初始化都将关闭。如果您没有明确初始化内存,则它处于随机状态。这是应用程序的调试/发布版本的行为方式不同。
检查此问题的简便方法是检查编译器警告 确保所有变量在使用前都已初始化(它将出现在警告中)。