对“pthread_create"的未定义引用——链接器命令选项顺序(目标文件之前/之后的库?) [英] Undefined reference to 'pthread_create' — linker command option order (libraries before/after object files?)

查看:19
本文介绍了对“pthread_create"的未定义引用——链接器命令选项顺序(目标文件之前/之后的库?)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

When I try to compile that, I receive a particular error. But, it's not possible because I use the right flag. In server.c there is the library pthread.h. So, how can I resolve my linking problem? I'm using 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

推荐答案

在目标文件之后列出库

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

List libraries after the object files

When linking only object files and libraries, list the libraries after the object files:

gcc -o Server1.exe -Wall -Wunused -ansi -pedantic -ggdb  Server1.o Util.o -lpthread -lm

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

When the linking command includes source files, list the source files and object files (if any) before the libaries. The -l options come at the end of the command line, therefore. Relevant -L options specifying where a library is found should come before the -l option specifying the library.

次要问题是:

为什么会起作用?

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

When the C compiler invokes the linker, it tells the linker to pull in some system object files with names like crt0.o, and tells it to look for a symbol main (or possibly _main(), depending on local naming conventions). It also supplies the object files and libraries in the order you specified on the command line. When it comes across an object file, the linker notes the definitions it provides, and the unsatisfied references it makes. When it comes across a library, it scans the library to see whether it can satisfy any unsatisfied references. If the library can supply any as yet unsatisfied references, then it includes (the relevant parts of) the library 'in the executable'. For a shared library, the linker ensures that the library will be loaded at runtime. For a static library, the linker includes the object files from the library that satisfy at least one reference, rescanning until there are no further references that can be satisfied. If the library satisfies no references, it is ignored. When the process is complete, if any references are still unsatisfied, you get the error messages.

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

So, in your scenario, you had -lpthread before either Server1.o or Util.o. Since -lpthread does not provide a main function and that was the only relevant unsatisfied symbol, it was ignored. The mathematics library, -lm may also have been ignored, or it may be an empty stub to keep code devised for other systems where the mathematics library is separate from the main C library. Then the linker read your object files, and found the reference to pthread_create(). When it scanned the C library -lc (libc.so) afterwards, it found symbols to satisfy everything except pthread_create.

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

When the libraries are listed after the object files, then the linker knew it needed pthread_create when it scanned -lpthread and ensured that the shared library would be loaded at runtime.

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

The discussion above is essentially platform-neutral. If you follow the 'libraries after object files' rule, your linker line has the maximum chance of working correctly on all platforms.

如果您在使用 GNU binutils 包,尤其是 GNU ld 命令的系统上,您可能会发现不同的行为.

If you are on a system using the GNU binutils package, and the GNU ld command in particular, you may find different behaviour.

Sourceware 的手册(如果你试试 http://www.gnu.org/software/binutils/manuals) 包括资料:

The manual from Sourceware (which is where you are redirected if you try http://www.gnu.org/software/binutils/manuals) includes the information:

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

--as-needed
--no-as-needed
This option affects ELF DT_NEEDED tags for dynamic libraries mentioned on the command line after the --as-needed option. Normally the linker will add a DT_NEEDED tag for each dynamic library mentioned on the command line, regardless of whether the library is actually needed or not. --as-needed causes a DT_NEEDED tag to only be emitted for a library that at that point in the link satisfies a non-weak undefined symbol reference from a regular object file or, if the library is not found in the DT_NEEDED lists of other libraries, a non-weak undefined symbol reference from another dynamic library. Object files or libraries appearing on the command line after the library in question do not affect whether the library is seen as needed. This is similar to the rules for extraction of object files from archives. --no-as-needed restores the default behaviour.

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

It appears that different versions of different systems use different values for the as-needed option. While the --no-as-needed behaviour is convenient in that it lets you order libraries and object files in more or less any order on your command line, it also means that all the libraries listed on the command line are loaded at run time, even if there are no symbols actually used from the library (thus --no-as-needed is equivalent to a hypothetical --whether-needed-or-not flag). Using the --as-needed option is the classic and portable behaviour.

有传言说,一些 Linux 发行版在过去 5 年的某个时间将其系统上的默认行为从 --no-as-needed 更改为 --as-needed几年左右(第三个千年的第二个十年的前半部分,为了争论).您可以在一些关于 SO 的问题中找到支持这一谣言的证据.

Rumour has it that some Linux distributions changed the default behaviour on their systems from --no-as-needed to --as-needed sometime in the last 5 years or so (the first half of the second decade of the third millennium, for sake of argument). You can find evidence in support of this rumour in a number of questions on SO.

这篇关于对“pthread_create"的未定义引用——链接器命令选项顺序(目标文件之前/之后的库?)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆