简体   繁体   English

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

[英]Anything other than -Ofast causes “undefined reference” error

I have a C program which includes math.h and makes use of the sqrt function from that header. 我有一个包含math.h的C程序,并使用了该标头中的sqrt函数。 Very strangely, when I do not pass the -Ofast flag, my code does not compile. 非常奇怪的是,当我不传递-Ofast标志时,我的代码无法编译。

If I use the following to compile my code: 如果我使用以下代码来编译我的代码:

gcc -std=c99 foo.c

Either by itself, or add any of -O1 , -O2 or -Os (those are uppercase O's) to that command, I get the following error: 通过其自身或任何添加-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 gives a similar, but more elaborate error (note that I don't call sqrt within main ): -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

However, -Ofast compiles without error and the program runs perfectly. 但是, -Ofast编译不会出错,并且程序可以完美运行。 So, 所以,

  • Why does this happen? 为什么会这样? Why must a certain optimization level be enabled for it to compile? 为什么必须启用某个优化级别才能进行编译? Is it a GCC bug? 是GCC错误吗?
  • How can I fix it, if I choose not to use -Ofast ? 如果选择不使用-Ofast ,该如何解决?

I'll try to phrase this as an answer based on the comments I've provided. 我将根据我提供的评论尝试将此短语作为答案。

Essentially -ffast-math allows for mathematical 'optimizations' that do not conform to the IEEE-754 standard. 本质上, -ffast-math允许不符合IEEE-754标准的数学“优化”。 Some examples includes allowing floating-point operations to obey the laws of associativity, eg, they behave like 'real' numbers: (a + b) + c == a + (b + c) - and this is not a correct assumption with floating-point numbers. 一些示例包括允许浮点运算遵循关联律,例如,它们的行为类似于“实数”: (a + b) + c == a + (b + c) -但这不是正确的假设浮点数字。 You can look at the man page for gcc to see the options that -ffast-math enables. 您可以在gcc的手册页中查看-ffast-math启用的选项。

The option also allows for other code generation options that depart from the IEEE-754 standard. 该选项还允许使用其他与IEEE-754标准不同的代码生成选项。 Operations that should raise exceptions, signalling NaNs, etc., may not be honoured. 应该引发异常,发信号通知NaN等的操作可能无法兑现。 The example in the comments was sqrt ; 评论中的示例是sqrt ; if we pass a negative value to sqrt , the results may not conform to the IEEE-754 standard. 如果我们将负值传递给sqrt ,则结果可能不符合IEEE-754标准。 Trying to find the source of these inconsistencies far outweighs any benefit on modern processors. 试图找到这些不一致的根源远远超过了现代处理器的任何好处。 Modern CPUs have massive floating point resources, and correctness is far more important than any misplaced sense of efficiency. 现代CPU具有大量的浮点资源,正确性比任何错位的效率意义都重要。

There are very real examples of where honouring the associative property of real numbers when dealing with floating-point numbers leads to incorrect results. 有非常真实的示例,其中在处理浮点数时尊重实数的关联属性会导致错误的结果。 One example is Kahan summation . 卡汉求和就是一个例子。 It relies on the non-associative property of floating-point arithmetic. 它依赖于浮点算术的非关联属性。 There are other examples where careful analysis of numeric algorithms rely on IEEE-754 properties. 还有其他一些例子,其中数字算法的仔细分析依赖于IEEE-754属性。 Another example is Heron's formula for the area of a triangle. 另一个例子是苍鹭的三角形面积公式

Numerical analysis is a broad field, and the IEEE-754 standards represent a very careful and well-researched effort to standardize the idiosyncratic behaviour of floating-point operations, and their deviation from the naive ideal of 'real' numbers. 数值分析是一个广阔的领域,IEEE-754标准代表了非常仔细和深入研究的工作,旨在标准化浮点运算的行为以及它们与“实数”的天真理想的偏离。 It represents a massive effort over decades of research and experience (not to mention frustration) in numerically intensive computation. 它代表了数十年的数字密集型计算研究和经验(更不用说沮丧)了。

There are people who frequently answer floating-point questions on this site with a much broader knowledge of the topic than I have. 有些人经常在该站点上回答浮点问题,并且对该主题的了解比我广泛得多。 I just hope to convince you that -ffast-math is simply ill-advised in many cases (often an algorithm with better numerical conditioning is a better first step), and introduce sources of error that are extremely difficult to find, with results that are often impossible to reproduce on other platforms. 我只是希望说服您-ffast-math在许多情况下都是错误的建议(通常,具有更好数值条件的算法是更好的第一步),并介绍极难发现的错误源,其结果是通常无法在其他平台上复制。 Avoid it like the plague. 避免像瘟疫一样。

The math library must be linked in when building the executable 构建可执行文件时必须链接数学库

so you need to compile with -lm option. 因此,您需要使用-lm选项进行编译。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 `clear` 导致未定义的引用错误 - `clear` causes undefined reference error -DNDEBUG with -Ofast比-Ofast慢 - -DNDEBUG with -Ofast is slower than only -Ofast EXPORT_SYMBOL 导致在一个方向上未定义的引用,而不是另一个方向(重定位被截断) - EXPORT_SYMBOL causes undefined reference in one direction, but not the other (relocation truncated) 未定义的函数引用从未使用/定义/任何东西? - Undefined reference to function never used/defined/anything? 为什么即使我包含 math.h 标头,也会收到“对 sqrt 的未定义引用”错误? 除了添加 -lm 之外,还有其他永久解决方案吗? - Why am I getting “undefined reference to sqrt” error even though I include math.h header? is there a permanent solution other than adding -lm? stdout除了控制台窗口之外还有什么吗? - Is stdout Ever Anything Other Than a Console Window? ncurses程序崩溃除了PuTTY以外的任何东西 - ncurses program crashes on anything other than PuTTY 仅当参数不是常量时,来自math.h的sqrt才会导致链接器错误“对sqrt的未定义引用” - sqrt from math.h causes linker error “undefined reference to sqrt” only when the argument is not a constant select() 如何返回除 -1、0 或 1 之外的任何值? - How would select() return anything other than -1, 0, or 1? 导致此链接失败的原因(未定义的引用)? - What causes this link failure (undefined reference)?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM