[英]Anything other than -Ofast causes “undefined reference” error
我有一个包含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
给出了类似但更详尽的错误(请注意,我不在main
内调用sqrt
):
/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
编译不会出错,并且程序可以完美运行。 所以,
-Ofast
,该如何解决? 我将根据我提供的评论尝试将此短语作为答案。
本质上, -ffast-math
允许不符合IEEE-754标准的数学“优化”。 一些示例包括允许浮点运算遵循关联律,例如,它们的行为类似于“实数”: (a + b) + c == a + (b + c)
-但这不是正确的假设浮点数字。 您可以在gcc
的手册页中查看-ffast-math
启用的选项。
该选项还允许使用其他与IEEE-754标准不同的代码生成选项。 应该引发异常,发信号通知NaN等的操作可能无法兑现。 评论中的示例是sqrt
; 如果我们将负值传递给sqrt
,则结果可能不符合IEEE-754标准。 试图找到这些不一致的根源远远超过了现代处理器的任何好处。 现代CPU具有大量的浮点资源,正确性比任何错位的效率意义都重要。
有非常真实的示例,其中在处理浮点数时尊重实数的关联属性会导致错误的结果。 卡汉求和就是一个例子。 它依赖于浮点算术的非关联属性。 还有其他一些例子,其中数字算法的仔细分析依赖于IEEE-754属性。 另一个例子是苍鹭的三角形面积公式 。
数值分析是一个广阔的领域,IEEE-754标准代表了非常仔细和深入研究的工作,旨在标准化浮点运算的行为以及它们与“实数”的天真理想的偏离。 它代表了数十年的数字密集型计算研究和经验(更不用说沮丧)了。
有些人经常在该站点上回答浮点问题,并且对该主题的了解比我广泛得多。 我只是希望说服您-ffast-math
在许多情况下都是错误的建议(通常,具有更好数值条件的算法是更好的第一步),并介绍极难发现的错误源,其结果是通常无法在其他平台上复制。 避免像瘟疫一样。
构建可执行文件时必须链接数学库
因此,您需要使用-lm
选项进行编译。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.