未定义的'pthread_create'引用 - 链接器命令选项顺序(目标文件之前/之后的库?)

rsc*_*rin 13 c ubuntu linker pthreads

当我尝试编译时,我收到一个特定的错误.但是,这是不可能的,因为我使用正确的旗帜.在server.c那里有图书馆pthread.h.那么,我该如何解决链接问题呢?我正在使用Linux(Ubuntu).

make
gcc -c -Wall -Wunused -ansi -pedantic -ggdb  -o Server1.o Server.c
gcc -c -Wall -Wunused -ansi -pedantic -ggdb  Util.c
gcc -o Server1.exe -Wall -Wunused -ansi -pedantic -ggdb -lpthread -lm Server1.o Util.o
Server1.o: In function `main':
/home/ruggero/ruggero_fine/Server.c:1002: undefined reference to `pthread_create'
collect2: ld returned 1 exit status
make: *** [Server1.exe] Errore 1
Run Code Online (Sandbox Code Playgroud)

Jon*_*ler 33

列出目标文件后的库

仅链接目标文件和库时,请在目标文件后列出库:

gcc -o Server1.exe -Wall -Wunused -ansi -pedantic -ggdb  Server1.o Util.o -lpthread -lm
Run Code Online (Sandbox Code Playgroud)

当链接命令包含源文件时,在库之前列出源文件和目标文件(如果有).因此,-l选项位于命令行的末尾.-L指定库的位置的相关选项应该在-l指定库的选项之前.

附属问题是:

它为什么有效?

当C编译器调用链接器时,它告诉链接器引入一些名称类似的系统对象文件crt0.o,并告诉它查找符号main(或者可能_main(),取决于本地命名约定).它还按照您在命令行中指定的顺序提供目标文件和库.当遇到目标文件时,链接器会记录它提供的定义,以及它所做的不满意的引用.当它遇到一个库时,它会扫描库以查看它是否能满足任何不满意的引用.如果库可以提供任何尚未满足的引用,那么它包括"可执行文件中的库"(的相关部分).对于共享库,链接器确保在运行时加载库.对于静态库,链接器包含库中满足至少一个引用的目标文件,重新扫描直到没有其他引用可以满足.如果库不满足引用,则忽略它.完成此过程后,如果仍未满足任何引用,则会收到错误消息.

所以,在你的场景中,你有或-lpthread之前.由于没有提供功能,而且这是唯一相关的不满意符号,因此被忽略了.数学库也可能被忽略,或者它可能是一个空的存根,以保留为数学库与主C库分开的其他系统设计的代码.然后链接器读取您的目标文件,并找到引用.当它之后扫描C库()时,它发现符号满足除了之外的所有内容.Server1.oUtil.o-lpthreadmain-lmpthread_create()-lclibc.sopthread_create

当在目标文件之后列出库时,链接器pthread_create在扫描时知道它需要-lpthread并确保在运行时加载共享库.

GNU ld--as-needed选项

上面的讨论基本上是平台中立的.如果遵循"库后目标文件"规则,则链接器行最有可能在所有平台上正常工作.

如果您使用的是GNU binutils软件包,ld特别是GNU 命令,则可能会发现不同的行为.

来自Sourceware的手册(如果你尝试http://www.gnu.org/software/binutils/manuals,你可以在哪里重定向)包括以下信息:

--as-needed
--no-as-needed
此选项会影响--as-needed选项后命令行中提到的动态库的ELF DT_NEEDED标记.通常,链接器将为命令行中提到的每个动态库添加DT_NEEDED标记,无论是否实际需要库.--as-needed导致只为库中发出DT_NEEDED标记,该库在链接中的该点满足来自常规对象文件的非弱未定义符号引用,或者,如果在其他库的DT_NEEDED列表中找不到库,则为非来自另一个动态库的弱未定义符号引用.在相关库之后出现在命令行上的对象文件或库不会影响是否根据需要查看库.这类似于从归档中提取目标文件的规则.--no-as-needed恢复默认行为.

看来不同系统的不同版本对该as-needed选项使用不同的值.虽然--no-as-needed行为很方便,因为它允许您在命令行上以或多或少的顺序对库和目标文件进行排序,但这也意味着命令行中列出的所有库都在运行时加载,即使没有符号也是如此实际上从库中使用(因此--no-as-needed相当于一个假设的--whether-needed-or-not标志).使用该--as-needed选项是经典且可移植的行为.

有传言说,一些Linux发行版更改了默认的行为对他们的系统,从--no-as-needed--as-needed在过去的5年左右的某个时候(上半年第三个千年的第二个十年,因为参数的缘故).你可以在关于SO的一些问题中找到支持这个谣言的证据.