Wan*_*ang 5 c c++ clang clang++ ubuntu-20.04
在 ubuntu 20.04 上,当我使用 clang-8 或 clang-9(clang 版本 9.0.1-12)编译包含对 libm 的引用的简单代码时,它将失败并显示错误“未定义的引用__pow_finite”
#include <math.h>
int main()
{
double x=1, y=1;
x = pow(x,y);
}
Run Code Online (Sandbox Code Playgroud)
clang-9 -lm test.c -ffast-math
/usr/bin/ld: /tmp/test-9b1a45.o: in function `main':
test.c:(.text+0x2a): undefined reference to `__pow_finite'
readelf -Ws /lib/x86_64-linux-gnu/libm.so.6| grep pow_finite
626: 000000000002ed90 65 IFUNC GLOBAL DEFAULT 17 __pow_finite@GLIBC_2.15
Run Code Online (Sandbox Code Playgroud)
gcc 没问题。知道这里有什么问题吗?
C++ 也有同样的问题:
#include <cmath>
int main()
{
double x=1, y=1;
x = pow(x,y);
}
Run Code Online (Sandbox Code Playgroud)
编辑
我实际上使用了-lm,我只是忘记放入文本。如果我不添加它,则是另一个错误。
$ clang-9 test.c
/usr/bin/ld: /tmp/test-3389a6.o: in function `main':
test.c:(.text+0x25): undefined reference to `pow'
$ gcc test.c
/usr/bin/ld: /tmp/cc21n4wb.o: in function `main':
test.c:(.text+0x39): undefined reference to `pow'
Run Code Online (Sandbox Code Playgroud)
F31没有这个问题。Godbolt也不错。一定是系统或特定的颠覆出了问题。
到目前为止顺序无关紧要,所以我认为不是gcc 不会正确包含 math.h:
clang-9 test.c -ffast-math -lm
/usr/bin/ld: /tmp/test-6dfc29.o: in function `main':
test.c:(.text+0x2a): undefined reference to `__pow_finite'
clang-9 -ffast-math test.c -lm
/usr/bin/ld: /tmp/test-6754bc.o: in function `main':
test.c:(.text+0x2a): undefined reference to `__pow_finite'
Run Code Online (Sandbox Code Playgroud)
将 ld 改为 collect2 也有同样的问题,所以应该不是 ld 的问题。
clang-9 -v -fuse-ld=/usr/lib/gcc/x86_64-linux-gnu/9/collect2 test.c -ffast-math -lm
Run Code Online (Sandbox Code Playgroud)
更新
它似乎与libc update相关。没有math-finite.h更多了,所以-ffast-math生成时__*finite它会失败。clang 必须改变它的行为。
TL;TR:这是 clang 中的一个错误,已在 clang-10 中修复。如果有人遇到同样的问题,请使用最新的 GCC 或 Clang 版本或设置-fno-finite-math-only.
造成这种情况的根本原因是clang错误地调用了libm中的一些非API函数:
它们只是一个 ABI(通过使用 -ffinite-math-only 或暗示它的选项来选择,这导致标头使用“asm”将调用重定向到某些 libm 函数),而不是 API。这一变化意味着 ABI 已变成兼容符号(仅适用于现有二进制文件,不适用于新链接的任何内容,根本不包含在静态 libm 中,也不包含在未来 glibc 端口(例如 RV32)的共享 libm 中),所以,是的,在在任何情况下,工具生成对这些函数的直接调用(而不是仅仅遵循标头中函数声明的“asm”注释),它们需要停止这样做。
Bug 已经在这里被跟踪并通过PR修复了,并且已经在 clang-10 中很长时间了。
有关删除这些内容的更多背景信息,请参阅提案:删除或减少 math-finite.h:
对于这个文件中的一些函数;pow、powf、log、logf、log2、log2f、exp、expf、exp2 和 exp2f;默认实现已得到改进,可以处理特殊情况,并且 *_finite 名称只是普通名称的别名,因此 asm 属性没有完成任何操作。