c - 对 'pthread_create' 的 undefined reference — 链接器命令选项顺序(目标文件之前/之后的库?)

标签 c ubuntu linker pthreads

这个问题在这里已经有了答案:





Undefined reference to pthread_create in Linux

(16 个答案)


7年前关闭。




当我尝试编译它时,我收到一个特定的错误。但是,这是不可能的,因为我使用了正确的标志。在 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

最佳答案

在目标文件之后列出库

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

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

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

附属问题是:

Why does it work?



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

所以,在你的场景中,你有 -lpthreadServer1.o 之前或 Util.o .由于-lpthread不提供 main功能,这是唯一相关的不满足符号,它被忽略了。数学图书馆,-lm也可能被忽略,或者它可能是一个空 stub ,用于保留为数学库与主 C 库分开的其他系统设计的代码。然后链接器读取您的目标文件,并找到对 pthread_create() 的引用。 .当它扫描 C 库时 -lc ( libc.so ) 之后,它找到了满足除 pthread_create 之外的所有内容的符号。 .

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

GNU ld--as-needed选项

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

如果您在使用 GNU binutils 的系统上包和 GNU ld特别是命令,您可能会发现不同的行为。

来自 Sourceware 的手册(如果您尝试 http://www.gnu.org/software/binutils/manuals ,您将被重定向到这里)包括以下信息:

--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 option 是经典且可移植的行为。

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

关于c - 对 'pthread_create' 的 undefined reference — 链接器命令选项顺序(目标文件之前/之后的库?),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9253200/

相关文章:

c - 无法链接 opencv 库

ios - 链接到 Xcode 上的 arm64 库时出现链接器错误

python - 创建python模块时出错

c - 如何保护Linux中进程间共享的内存

linux - 如何让 Ubuntu 成功搜索许可证的环境变量?

java - 安装 sun-java6-jre 报错

mysql - sqoop 1.99.5 安装错误 - 无法访问 mysql 5.6 的 JDBC 连接器(在 Ubuntu 节点上运行的 hadoop 2.4.1 集群)

linker - 如何将目标文件链接到 UEFI DXE/EFI 驱动程序?

c++ - 在内存中为多个文件保存构造的静态数组c++

c - 从数组读取时出现段错误