GCC将无法正常包括文件math.hGCC将无法正常包括文件math.h(gcc will not

2019-06-14 14:49发布

下面是一个小例子,概述了我的问题

test.c的:

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

main ()
{
   fmod ( 3, 2 );
}

这里是我发出来编译命令test.c

gcc -lm test.c -o test

这里是输出我得到的,当我发出上述命令

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

我得到的结果相同,如果不是我用cc 。 我用gcc以下版本

gcc-4.6.real (Ubuntu/Linaro 4.6.1-9ubuntu3) 4.6.1

任何想法,为什么我的程序将无法编译?

Answer 1:

问题是从连接体,来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中的之前运行的功能和主后设置的环境了。 你可以看到,现在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


Answer 2:

从GCC(1)手册页:“-l选项的位置是显著。”

特别:

  -llibrary -l library Search the library named library when linking. (The second alternative with the library as a separate argument is only for POSIX compliance and is not recommended.) It makes a difference where in the command you write this option; the linker searches and processes libraries and object files in the order they are specified. Thus, foo.o -lz bar.o searches library z after file foo.o but before bar.o. If bar.o refers to functions in z, those functions may not be loaded. The linker searches a standard list of directories for the library, which is actually a file named liblibrary.a. The linker then uses this file as if it had been specified precisely by name. The directories searched include several standard system directories plus any that you specify with -L. Normally the files found this way are library files---archive files whose members are object files. The linker handles an archive file by scanning through it for members which define symbols that have so far been referenced but not defined. But if the file that is found is an ordinary object file, it is linked in the usual fashion. The only difference between using an -l option and specifying a file name is that -l surrounds library with lib and .a and searches several directories. 


文章来源: gcc will not properly include math.h