简体   繁体   English

gcc优化导致app失败

[英]gcc optimizations cause app to fail

I'm having a real strange problem using GCC for ARM with the optimizations turned on. 我在使用GCC for ARM时出现了一个非常奇怪的问题,并且启用了优化。 Compiling my C++ application without the optimizations produces an executable that at runtime outputs the expected results. 在没有优化的情况下编译我的C ++应用程序会生成一个可执行文件,在运行时输出预期的结果。 As soon as I turn on the optimizations - that is -O1 - my application fails to produce the expected results. 一旦我打开优化 - 即-O1 - 我的应用程序就无法产生预期的结果。 I tried for a couple of days to spot the problem but I'm clueless. 我试了几天才发现问题,但我很无能为力。 I eliminated any uninitialized variables from my code, I corrected the spots where strict aliasing could cause problems but still I do not have the proper results. 我从我的代码中删除了任何未初始化的变量,我纠正了严格混叠可能导致问题但仍然没有正确结果的位置。

I'm using GCC 4.2.0 for ARM(the processor is an ARM926ej-s) and running the app on a Montavista Linux distribution. 我正在使用GCC 4.2.0 for ARM(处理器是ARM​​926ej-s)并在Montavista Linux发行版上运行该应用程序。

Below are the flags I'm using: 以下是我正在使用的标志:

-O1 -fno-unroll-loops fno-merge-constants -fno-omit-frame-pointer -fno-toplevel-reorder \
-fno-defer-pop -fno-function-cse -Wuninitialized -Wstrict-aliasing=3 -Wstrict-overflow=3 \
-fsigned-char -march=armv5te -mtune=arm926ej-s -ffast-math

As soon as I strip the -O1 flag and recompile/relink the application I get the proper output results. 一旦我剥离-O1标志并重新编译/重新链接应用程序,我就会得到正确的输出结果。 As you can see from the flags I tried to disable any optimization I thought it might cause problems but still no luck. 正如你从旗帜中看到我试图禁用任何优化我认为它可能会导致问题,但仍然没有运气。

Does anyone have any pointers on how I could further tackle this problem? 有没有人对如何进一步解决这个问题有任何指示?

Thanks 谢谢

Generally speaking, if you say "optimization breaks my program", it is 99.9% your programm that is broken. 一般来说,如果你说“优化打破了我的程序”,你的程序就会被破坏99.9%。 Enabling optimizations only uncovers the faults in your code. 启用优化仅揭示代码中的错误。

You should also go easy on the optimization options. 您还应该轻松完成优化选项。 Only in very specific circumstances will you need anything else beyond the standard options -O0, -O2, -O3 and perhaps -Os. 只有在非常特殊的情况下,您才需要除标准选项-O0,-O2,-O3和-Os之外的任何其他选项。 If you feel you do need more specific settings than that, heed the mantra of optimizations: 如果您觉得确实需要更多特定设置,请注意优化的口号:

Measure, optimize, measure. 测量,优化,测量。

Never go by "gut feeling" here. 永远不要去这里“直觉”。 Prove that a certain non-standard optimization option does significantly benefit your application, and understand why (ie, understand exactly what that option does, and why it affects your code). 证明某个非标准优化选项确实有效地使您的应用程序受益, 并理解为什么 (即,准确理解该选项的作用以及它为什么会影响您的代码)。

This is not a good place to navigate blindfolded. 这不是蒙住眼睛的好地方。

And seeing how you use the most defensive option (-O1), then disable half a dozen optimizations, and then add -ffast-math, leads me to assume you're currently doing just that. 看看你如何使用防御性最强的选项(-O1),然后禁用六个优化, 然后添加-ffast-math,让我假设你正在做这个。

Well, perhaps one-eyed. 好吧,也许是独眼。

But the bottom line is: If enabling optimization breaks your code, it's most likely your code's fault. 但最重要的是:如果启用优化会破坏您的代码,那么很可能是代码的错误。

EDIT: I just found this in the GCC manual: 编辑:我刚刚在GCC手册中找到了这个:

-ffast-math : This option should never be turned on by any -O option since it can result in incorrect output for programs which depend on an exact implementation of IEEE or ISO rules/specifications for math functions. -ffast-math :任何-O选项都不应该打开此选项,因为它可能导致程序的输出不正确,这取决于IEEE或ISO规则/规范的数学函数的确切实现。

This does say, basically, that your -O1 -ffast-math could indeed break correct code. 这确实说,基本上,你的-O1 -ffast-math确实可以破坏正确的代码。 However, even if taking away -ffast-math removes your current problem, you should at least have an idea why . 然而,即使拿走-ffast-math消除你当前的问题,你至少应该知道为什么 Otherwise you might merely exchange your problem now with a problem at a more inconvenient moment later (like, when your product breaks at your client's location). 否则,你可能只是现在有一个问题,在一个更加不方便时刻交换你的问题 (比如,当你的产品打破你的客户端的位置)。 Is it really -ffast-math that was the problem, or do you have broken math code that is uncovered by -ffast-math ? 这是真的-ffast-math是问题,还是你已经破坏了-ffast-math 发现的数学代码?

-ffast-math should be avoided if possible. 如果可能,应该避免使用-ffast-math Just use -O1 for now and drop all the other optimisation switches. 现在只需使用-O1并删除所有其他优化开关。 If you still see problems then it's time to start debugging. 如果您仍然遇到问题,那么就该开始调试了。

Without seeing your code, it's hard to get more specific than "you probably have a bug". 没有看到你的代码,很难比“你可能有一个bug”更具体。

There are two scenarios where enabling optimizations changes the semantics of the program: 有两种情况,启用优化会更改程序的语义:

  • there is a bug in the compiler, or 编译器中有一个错误,或者
  • there is a bug in your code. 您的代码中存在错误。

The latter is probably the most likely. 后者可能是最有可能的。 Specifically, you probably rely on Undefined Behavior somewhere in your program. 具体来说,您可能依赖于程序中某处的未定义行为。 You rely on something that just so happen to be true when you compile using this compiler on this computer with these compiler flags, but which isn't guaranteed by the language. 当你在台带有这些编译器标志的计算机上使用这个编译器进行编译时,你依赖的东西恰好是正确的,但语言无法保证。 And so, when you enable optimizations, GCC is under no obligation to preserve that behavior. 因此,当您启用优化时,GCC没有义务保留该行为。

Show us your code. 告诉我们你的代码。 Or step through it in the debugger until you get to the point where things go wrong. 或者在调试器中逐步执行它,直到出现问题为止。

I can't be any more specific. 我不能再具体了。 It might be a dangling pointer, uninitialized variables, breaking the aliasing rules, or even just doing one of the many things that yield undefined results (like i = i++ ) 它可能是一个悬空指针,未初始化的变量,打破别名规则,甚至只是做了许多产生未定义结果的东西之一(比如i = i++

Try to make a minimal test case. 尝试制作一个最小的测试用例。 Rewrite the program, removing things that don't affect the error. 重写程序,删除不影响错误的内容。 It's likely that you'll discover the bug yourself in the process, but if you don't, you should have a one-screen example program you can post. 您可能会在此过程中自己发现错误,但如果不这样做,您应该有一个可以发布的单屏示例程序。

Incidentally, if , as others have speculated, it is -ffast-math which causes your trouble (ie compiling with just -O1 works fine), then it is likely you have some math in there you should rewrite anyhow. 顺便说一句, 如果像其他人纷纷猜测,这是-ffast-math这将导致你的麻烦(即只编译-O1正常工作),那么很可能你有一些数学在那里,你应该重写无论如何。 It's a bit of an over-simplification, but -ffast-math permits the compiler to essentially rearrange computations as you could abstract mathematical numbers - even though doing so on real hardware may cause slightly different results since floating point numbers aren't exact. 这有点过分简化,但是-ffast-math允许编译器基本上重新排列计算,因为你可以抽象数学数字 - 即使在真实硬件上这样做可能会导致稍微不同的结果,因为浮点数不准确。 Relying on that kind of floating point detail is likely to be unintentional. 依赖于那种浮点细节可能是无意的。

If you want to understand the bug, a minimal test-case is critical in any case. 如果你想了解这个bug,那么最小的测试用例在任何情况下都是至关重要的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM