其他什么比-Ofast导致“未定义的引用”错误(Anything other than -Ofast

2019-10-20 18:24发布

我有一个C程序,其中包括math.h和利用了的sqrt从该头的功能。 很奇怪的是,当我没有通过-Ofast标志,我的代码不能编译。

如果我用下面的编译我的代码:

gcc -std=c99 foo.c

通过其自身或任何添加-O1-O2-Os (这些都是大写字母O的),以该命令,我收到以下错误:

/tmp/ccAcT2Bz.o: In function `sum_of_divisors':
foo.c:(.text+0xb): undefined reference to `sqrt'
collect2: error: ld returned 1 exit status

-O3给出了一个类似的,但更详细的错误(请注意,我不叫sqrtmain ):

/tmp/ccBKvvFS.o: In function `sum_of_divisors':
foo.c:(.text+0x5c): undefined reference to `sqrt'
/tmp/ccBKvvFS.o: In function `main':
foo.c:(.text.startup+0xe5): undefined reference to `sqrt'
foo.c:(.text.startup+0xf3): undefined reference to `sqrt'
collect2: error: ld returned 1 exit status

然而, -Ofast编译没有错误,程序运行非常好。 所以,

  • 为什么会出现这种情况? 为什么一定要在一定的优化级别启用它来编译? 它是一个GCC的bug?
  • 我怎么能解决这个问题,如果我选择不使用-Ofast

Answer 1:

我会尽力短语这是基于我所提供的意见答复。

从本质上讲-ffast-math允许数学“优化”不符合IEEE-754标准。 一些例子包括允许浮点运算遵守关联的法律,例如,它们更像“真正”的数字: (a + b) + c == a + (b + c) -这是不是一个正确的假设与浮点数字。 你可以看一下手册页gcc看到的选项-ffast-math启用。

该选项还允许从IEEE-754标准之外的其它代码生成选项。 应引发异常,信号NaN等,操作可能无法兑现。 在评论这个例子是sqrt ; 如果我们通过一个负值, sqrt ,结果可能不符合IEEE-754标准。 试图找出这些矛盾的根源远远超过现代处理器的任何好处。 现代CPU具有巨大的浮点运算资源,和正确性是不是效率的任何错位的意义更为重要。

还有的地方用浮点数字打交道时尊重实数的关联属性导致不正确的结果非常现实的例子。 一个例子是Kahan的总和 。 它依靠浮点运算的非关联性质。 在有些情况下的数值算法仔细分析依赖于IEEE-754性能的其它例子。 另一个例子是海伦公式为三角形的面积。

数值分析是一个广泛的领域,和IEEE-754标准,代表了非常谨慎和周密研究的努力来规范浮点运算的特殊行为,以及“真实”号的天真理想的偏差。 它代表了几十年的研究和经验(更不用提沮丧)在数字密集型计算的巨大的努力。

有些人谁经常回答这个网站浮点问题比我的话题更广泛的知识。 我只是希望说服你, -ffast-math是简单地在许多情况下(通常具有更好的数值调节的算法是一个更好的第一步)不明智的,并引入误差是很难找到的来源,其结果是往往不可能复制在其他平台上。 避免像瘟疫。



Answer 2:

数学库必须在构建可执行文件时链接

所以你需要编译-lm选项。



文章来源: Anything other than -Ofast causes “undefined reference” error