gcc 优化导致应用程序失败

发布于 2024-09-26 03:38:09 字数 704 浏览 0 评论 0原文

我在打开优化后使用适用于 ARM 的 GCC 时遇到了一个非常奇怪的问题。 编译我的 C++ 应用程序而不进行优化会生成一个可执行文件 在运行时输出预期结果。当我打开电源时 优化 - 即 -O1 - 我的应用程序无法产生预期的结果。 我尝试了几天来发现问题,但我一无所知。 我从代码中消除了所有未初始化的变量,更正了以下位置 严格的别名可能会导致问题,但我仍然没有得到正确的结果。

我正在使用 GCC 4.2.0 for ARM(处理器是 ARM926ej-s)并运行该应用程序 在 Montavista Linux 发行版上。

以下是我正在使用的标志:

-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

一旦我删除 -O1 标志并重新编译/重新链接应用程序,我就会得到正确的输出结果。正如您从标志中看到的那样,我尝试禁用任何优化,我认为这可能会导致问题,但仍然没有运气。

有谁对我如何进一步解决这个问题有任何指示?

谢谢

I'm having a real strange problem using GCC for ARM with the optimizations turned on.
Compiling my C++ application without the optimizations produces an executable that
at runtime outputs the expected results. As soon as I turn on the
optimizations - that is -O1 - my application fails to produce the expected results.
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.

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. 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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

骄傲 2024-10-03 03:38:09

一般来说,如果你说“优化破坏了我的程序”,那么 99.9% 的程序都被破坏了。启用优化只能发现代码中的错误。

您还应该轻松选择优化选项。只有在非常特殊的情况下,您才需要标准选项 -O0、-O2、-O3 甚至 -Os 之外的其他选项。如果您认为您确实需要比这更具体的设置,请注意优化的口头禅:

测量、优化、测量。

永远不要遵循“直觉”感觉”在这里。证明某个非标准优化选项确实对您的应用程序有显着好处,并了解原因(即,准确了解该选项的作用以及它为何影响您的代码)。

这不是一个蒙着眼睛导航的好地方。

看看你如何使用最具防御性的选项(-O1),然后禁用六个优化,然后添加 -ffast-math,让我假设你目前正在这样做。

好吧,也许是独眼。

但底线是:如果启用优化破坏了您的代码,则很可能是您的代码的错误。

编辑:我刚刚在 GCC 手册中找到了这一点:

-ffast-math:任何 -O 选项都不应打开此选项
因为它可能会导致依赖于的程序输出不正确
IEEE 或 ISO 数学规则/规范的精确实现
功能。

基本上,这确实表明您的 -O1 -ffast-math 确实可能会破坏正确的代码。然而,即使去掉 -ffast-math 可以解决您当前的问题,您至少应该知道为什么。否则,您可能只是将现在的问题与稍后更不方便的时刻的问题交换(例如,当您的产品在客户所在地发生故障时)。问题真的是 -ffast-math 吗?或者您是否破坏了 -ffast-math发现的数学代码?

Generally speaking, if you say "optimization breaks my program", it is 99.9% your programm that is broken. 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. 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 (i.e., 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.

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:

-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.

This does say, basically, that your -O1 -ffast-math could indeed break correct code. However, even if taking away -ffast-math removes your current problem, you should at least have an idea why. 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?

笑咖 2024-10-03 03:38:09

如果可能,应避免 -ffast-math。现在只需使用 -O1 并删除所有其他优化开关。如果您仍然发现问题,那么就该开始调试了。

-ffast-math should be avoided if possible. Just use -O1 for now and drop all the other optimisation switches. If you still see problems then it's time to start debugging.

热情消退 2024-10-03 03:38:09

如果没有看到你的代码,很难比“你可能有一个错误”更具体。

在两种情况下,启用优化会更改程序的语义:

  • 编译器中存在错误,或者
  • 代码中存在错误。

后者可能是最有可能的。具体来说,您可能依赖于程序中某处的未定义行为。当您在计算机上使用这些编译器标志使用这个编译器进行编译时,您所依赖的东西恰好是正确的,但它不是' t 由语言保证。因此,当您启用优化时,GCC 没有义务保留该行为。

向我们展示您的代码。或者在调试器中逐步执行它,直到出现问题为止。

我不能说得更具体了。它可能是悬空指针、未初始化的变量、违反别名规则,甚至只是执行了产生未定义结果的众多操作之一(例如 i = i++

Without seeing your code, it's hard to get more specific than "you probably have a 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.

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++)

桜花祭 2024-10-03 03:38:09

尝试制作一个最小的测试用例。重写程序,删除不影响错误的内容。您很可能会在此过程中自己发现错误,但如果您没有发现,您应该有一个可以发布的单屏示例程序。

顺便说一句,如果,正如其他人推测的那样,是 -ffast-math 导致了您的麻烦(即仅使用 -O1 编译就可以正常工作) ,那么很可能你有一些数学知识,无论如何你都应该重写。这有点过于简化,但是 -ffast-math 允许编译器本质上重新安排计算,就像您可以抽象数学数字一样 - 尽管在真实硬件上这样做可能会导致与浮点略有不同的结果数字并不准确。依赖这种浮点细节可能是无意的。

如果您想了解该错误,那么最小的测试用例无论如何都是至关重要的。

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 (i.e. compiling with just -O1 works fine), then it is likely you have some math in there you should rewrite anyhow. 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. 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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文