繁体   English   中英

-Ofast以外的任何其他东西都会导致“未定义的引用”错误

[英]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编译不会出错,并且程序可以完美运行。 所以,

  • 为什么会这样? 为什么必须启用某个优化级别才能进行编译? 是GCC错误吗?
  • 如果选择不使用-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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM