除-Ofast之外的任何内容都会导致“未定义的引用”错误 [英] Anything other than -Ofast causes "undefined reference" error

查看:126
本文介绍了除-Ofast之外的任何内容都会导致“未定义的引用”错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个包含 math.h 的C程序,并利用该头文件中的 sqrt 函数。奇怪的是,当我没有通过 -Ofast 标志时,我的代码不能编译。



如果我使用以下来编译我的代码:

  gcc -std = c99 foo.c 

可以自行添加任何 -O1 -O2 -Os (这些都是大写的O)到这个命令,我得到以下错误:

  /tmp/ccAcT2Bz.o:在函数`sum_of_divisors'中:
foo.c :( .text + 0xb):对`sqrt'的未定义引用
collect2:error:ld返回1退出状态

-O3 给出了一个类似但更复杂的错误(注意,我不在 main 中调用 sqrt ) :

  /tmp/ccBKvvFS.o:函数`sum_of_divisors':
foo.c :( .text + 0x5c):`sqrt'的未定义引用
/tmp/ccBKvvFS.o:在函数`main'中:
foo.c :( .text.startup + 0xe5):未定义引用`sqrt'
foo.c :(。text.sta rtup + 0xf3):对`sqrt'的未定义引用
collect2:错误:ld返回1退出状态



然而, -Ofast 编译时没有错误,程序运行完美。所以,


  • 为什么会发生这种情况?为什么必须启用某个优化级别才能编译?它是一个GCC错误?

  • 如果我选择不使用 -Ofast
  • $,我该如何解决它? b $ b

解决方案

我会尝试根据我提供的评论来回答这个问题。



基本上 -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公式



数值分析是一个广泛的领域,而IEEE-754标准是一个非常仔细和精心研究的工作,用于标准化浮点运算的特殊行为,以及它们偏离真正的数字。它代表了数十年的研究和经验(更不用说沮丧)在数值密集型计算中的巨大努力。

有些人经常回答这个网站上的浮点问题对这个话题的了解比我更广泛。我只是希望说服你,在很多情况下, -ffast-math 是很不明智的(通常一个更好的数值调节算法是更好的第一步),并且介绍源非常难以找到的错误,其结果往往不可能在其他平台上重现。避免它像瘟疫一样。


I have a C program which includes math.h and makes use of the sqrt function from that header. Very strangely, when I do not pass the -Ofast flag, my code does not compile.

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:

/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):

/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. So,

  • Why does this happen? Why must a certain optimization level be enabled for it to compile? Is it a GCC bug?
  • How can I fix it, if I choose not to use -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. Some examples includes allowing floating-point operations to obey the laws of associativity, e.g., they behave like 'real' numbers: (a + b) + c == a + (b + c) - and this is not a correct assumption with floating-point numbers. You can look at the man page for gcc to see the options that -ffast-math enables.

The option also allows for other code generation options that depart from the IEEE-754 standard. Operations that should raise exceptions, signalling NaNs, etc., may not be honoured. The example in the comments was sqrt; if we pass a negative value to sqrt, the results may not conform to the IEEE-754 standard. 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.

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. 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. 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. Avoid it like the plague.

这篇关于除-Ofast之外的任何内容都会导致“未定义的引用”错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆