【发布时间】:2013-12-16 16:07:15
【问题描述】:
我有一些代码是用 GCC 编译的。我注意到在编译调试版本时,系统工作得很好。但是当我编译发布版本时,系统无法启动。
在解决这个问题一段时间后,我将问题缩小到一个函数,如果我指定一个较小的优化级别(-O0 而不是 -Os),系统将在发布版本中正常启动。因此,可能有一个 -Os 设置的标志导致该特定函数中的代码不起作用。
我计划通过获取 -Os 设置的所有标志并找到导致系统无法启动的标志来追踪潜在问题。
我正在尝试执行以下操作:
__attribute__ ((optimize("-fauto-inc-dec", "-fcompare-elim", "-fcprop-registers", "-fdce", "-fdefer-pop", "-fdelayed-branch", "-fdse", "-fguess-branch-probability", "-fif-conversion2", "-fif-conversion", "-fipa-pure-const", "-fipa-profile", "-fipa-reference", "-fmerge-constants", "-fsplit-wide-types", "-ftree-bit-ccp", "-ftree-builtin-call-dce", "-ftree-ccp", "-ftree-ch", "-ftree-copyrename", "-ftree-dce", "-ftree-dominator-opts", "-ftree-dse", "-ftree-forwprop", "-ftree-fre", "-ftree-phiprop", "-ftree-sra", "-ftree-pta", "-ftree-ter", "-funit-at-a-time")))
然后消除标志,直到系统启动。问题是,我一直在缩小范围并缩小范围,直到我发现我什至无法设置一个标志并让系统启动。
所以现在我认为我设置优化的方式有问题。如果我在这些标志中间的某个地方放置了一个多余的不存在的标志,比如 -fiam-fake-flag,编译器会检测到它并吐出一个错误(这起初让我觉得我正确设置了这些标志) .
我不想使用 pragma,因为:
" 在此之后定义的每个函数都如同为该函数指定了属性((optimize("STRING")))。"
我只想优化这一功能,以便缩小问题范围。
那么,我是否错误地设置了这些标志?有没有更好的方法来为一个特定的函数指定一大堆编译器标志?
如果不是在 micro 上运行,我可以在 Makefile 中指定我想要的所有标志并将其应用于所有函数,但这样做会使程序太大而无法在 micro 上运行。
【问题讨论】:
-
99.9% 的“设置 -0X 的代码有效/无效”是 UB 风格的错误。
-
@MartinJames:对于标准平台,我同意(100%)该统计数据。但是,如果 OP 正在使用一些带有不成熟工具链的古怪微控制器,根据我的经验,存在编译器错误的可能性 >0.1%...
-
@OliCharlesworth - 我一直在 ARM uC 上得到它。它一直是UB-ish,即。我蹩脚的代码:(
-
我知道是什么代码破坏了系统的启动能力,但希望了解原因。我正在构建 FreeRTOS。有问题的代码是 SPI 消息之间的强制延迟。在一个有自己线程的模块中,我启动一个计时器并取消设置一个标志。在标志被重置之前无法发送消息。在计时器到期时,标志被重置。计时器,一个 FreeRTOS 模块,应该是线程安全的,但是当它尝试设置标志时,计时器卡住了。如果无法发送消息,系统将无法启动。
-
但问题是,为什么不同的优化级别会影响定时器的过期和正确设置标志的能力?
标签: c optimization gcc attributes eabi