问题出在链接器
ld
上,而不是gcc(因此有退出状态消息)。通常情况下,ld要求按照顺序指定对象和库:
user
supplier
,其中
user
是使用库函数的对象,
supplier
是提供它的对象。
当您的
test.c
编译为一个对象时,编译器会声明fmod是未定义的引用。
$ gcc -c test.c
$ nm test.o
U fmod
0000000000000000 T main
(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
大多数涉及libc函数,这些函数在main函数之前和之后运行以设置环境。您可以看到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
将
-lm
放在链接器命令中
test.o
后面,可以成功链接。检查符号fmod现在应该已经被解析为实际地址,而确实如此。
$ gcc -static test.o -lm
$ nm a.out | grep fmod
0000000000400480 T __fmod
0000000000402b80 T __ieee754_fmod
0000000000400480 W fmod