gcc不会正确包含math.h

puk*_*puk 19 c linker gcc static-libraries

这是一个概述我的问题的最小例子

test.c的:

#include <stdio.h>
#include <math.h>

main ()
{
   fmod ( 3, 2 );
}
Run Code Online (Sandbox Code Playgroud)

这是我要编译的命令 test.c

gcc -lm test.c -o test
Run Code Online (Sandbox Code Playgroud)

这是我发出上述命令时得到的输出

/tmp/ccQmRk99.o: In function `main':
test.c:(.text+0x3e): undefined reference to `fmod'
collect2: ld returned 1 exit status
Run Code Online (Sandbox Code Playgroud)

如果相反,我会使用相同的输出cc.我使用的是以下版本的gcc

gcc-4.6.real (Ubuntu/Linaro 4.6.1-9ubuntu3) 4.6.1
Run Code Online (Sandbox Code Playgroud)

我的程序无法编译的任何想法?

Sco*_*les 52

问题来自链接器,ld而不是gcc(因此退出状态消息).通常,ld要求按顺序指定对象和库user supplier,其中user是使用库函数supplier的对象,并且是提供它的对象.

当您test.c编译为对象时,编译器声明fmod是未定义的引用

$ gcc -c test.c
$ nm test.o
                 U fmod
0000000000000000 T main
Run Code Online (Sandbox Code Playgroud)

(nm列出了目标文件引用的所有函数)

链接器将未定义的引用更改为已定义的引用,查找引用以查看它们是否在其他文件中提供.

$ gcc -lm test.o
$ nm a.out
0000000000600e30 d _DYNAMIC
0000000000600fe8 d _GLOBAL_OFFSET_TABLE_
00000000004006a8 R _IO_stdin_used
                 w _Jv_RegisterClasses
0000000000600e10 d __CTOR_END__
...
0000000000601018 D __dso_handle
                 w __gmon_start__
...
                 U __libc_start_main@@GLIBC_2.2.5
0000000000601020 A _edata
0000000000601030 A _end
0000000000400698 T _fini
0000000000400448 T _init
0000000000400490 T _start
00000000004004bc t call_gmon_start
0000000000601020 b completed.7382
0000000000601010 W data_start
0000000000601028 b dtor_idx.7384
                 U fmod@@GLIBC_2.2.5
0000000000400550 t frame_dummy
0000000000400574 T main
Run Code Online (Sandbox Code Playgroud)

其中大多数是指在main之前和之后运行的libc函数,用于设置环境.您可以看到fmod现在指向glibc,它将由共享库系统解析.

我的系统默认设置为使用共享库.如果我改为强制静态链接,我会得到你看到的顺序依赖

$ gcc -static -lm test.o
test.o: In function `main':
test.c:(.text+0x40): undefined reference to `fmod'
collect2: ld returned 1 exit status
Run Code Online (Sandbox Code Playgroud)

-lm后面的链接器命令,之后 test.o,允许其成功链接.检查符号fmod现在应解析为实际地址,实际上是

$ gcc -static test.o -lm
$ nm a.out | grep fmod
0000000000400480 T __fmod
0000000000402b80 T __ieee754_fmod
0000000000400480 W fmod
Run Code Online (Sandbox Code Playgroud)

  • 是.除非您有特殊需要,否则库**始终属于链接命令行的末尾**.并且它们属于依赖顺序,即如果A依赖于B,则B必须始终位于命令行上的A之后. (7认同)