除-Ofast以外的任何内容都会导致“未定义的引用”错误

时间:2014-08-22 04:54:17

标签: c gcc optimization linker gcc4.8

我有一个包含math.h的C程序,并使用该标头中的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提供了类似但更详细的错误(请注意,我不会在sqrt内致电main):

/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的错误吗?
  • 如果我选择不使用-Ofast
  • ,我该如何解决?

2 个答案:

答案 0 :(得分:4)

我会根据我提供的评论,将此作为答案。

基本上-ffast-math允许数学优化'不符合IEEE-754标准。一些示例包括允许浮点运算遵守关联性定律,例如,它们表现得像“真实”一样。数字:(a + b) + c == a + (b + c) - 这是一个带有浮点数的正确假设。您可以查看gcc的手册页,查看-ffast-math启用的选项。

该选项还允许其他代码生成选项偏离IEEE-754标准。应该引起异常,信号NaN等的操作可能不会受到尊重。评论中的示例是sqrt;如果我们将负值传递给sqrt,结果可能不符合IEEE-754标准。试图找到这些不一致的来源远远超过现代处理器的任何好处。现代CPU具有大量的浮点资源,正确性远比任何错位的效率感更重要。

在处理浮点数时,有一些非常实际的例子表明尊重实数的关联属性会导致错误的结果。一个例子是Kahan summation。它依赖于浮点运算的非关联属性。还有其他一些例子,仔细分析数值算法依赖于IEEE-754属性。对于三角形区域,另一个例子是Heron's formula

数值分析是一个广泛的领域,IEEE-754标准代表了一种非常仔细和充分研究的努力,以标准化浮点运算的特殊行为,以及它们与真实&#真实&#的天真理想的偏离39;数字。它代表了数十年研究和经验(更不用说挫折)在数字密集计算方面的巨大努力。

有些人经常在这个网站上回答浮点问题,而且对这个主题的了解比我更广泛。我只是希望说服你-ffast-math在很多情况下都是不明智的(通常一个具有更好数值条件的算法是更好的第一步),并引入极难找到的错误来源,结果是通常无法在其他平台上重现。避免像瘟疫一样。

答案 1 :(得分:1)

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

因此您需要使用-lm选项进行编译。