我最近上了一门使用 pthreads 的课程,在编译时我们被告知要添加
-lpthread
。但是为什么当对系统头文件使用其他#include <>
语句时,对象实现代码的链接似乎是自动发生的?例如,如果我只想获取头文件#include <stdio.h>
,我在编译时不需要-l
选项,那么.o
实现文件的链接就会发生。
编译器隐式链接标准 C 库 libc.a,因此不需要
-lc
参数。 Pthreads 是一个系统库,但不是 C 标准库的一部分,因此必须显式链接。
-nolibc
,则需要显式链接 libc(或某些替代 C 库)。
如果所有系统库都是隐式链接的,则 gcc 必须针对每个系统有不同的实现(例如 pthreads 不是 Windows 上的系统库),并且如果系统引入了新库,则 gcc 必须更改锁定步。 此外,当以某种未知的顺序搜索每个库以解析符号时,链接时间会增加。 C 标准库是编译器可以依赖在任何特定实现中提供的一个库,因此隐式链接通常是安全的且简单方便。
基本答案: -lpthreads 告诉编译器/链接器链接到 pthreads 库。
更长的答案
标头告诉编译器,稍后链接代码时某个函数将可用(有时该函数在标头中定义,可能是内联的)。因此,编译器将函数标记为基本可用,但稍后在链接阶段,链接器必须将函数调用连接到实际函数。系统头文件中的许多函数都是链接器自动使用的“C 运行时库”的一部分,但其他函数由外部库(例如 pthreads)提供。在由外部库提供的情况下,您必须使用“-lxxx”,以便编译器/链接器知道要在进程中包含哪个外部库,以便正确获取函数的地址。
希望有帮助
C 头文件不包含函数的实现。它只包含函数原型,以便编译器可以生成正确的函数调用。
实际的实现存储在库中。最常用的函数(例如
printf
和 malloc
)在标准 C 库 (LibC) 中实现,该库隐式链接到任何可执行文件,除非您请求不链接它。线程支持是在一个单独的库中实现的,必须通过将 -pthread
选项传递给链接器来显式链接该库。
注意:您可以将选项
-pthread
传递给编译器 ,这也将链接适当的库。
对于这个文件
#include <stdio.h>
int main() {
return 0;
}
奔跑
gcc -v -o simple simple.c
您将会看到 gcc 实际上做了什么。你会看到它在你背后与图书馆链接。这就是为什么您没有明确指定标准 C 库的原因。
默认搜索一些库文件,只是为了方便,基本上都是C标准库。链接器可以选择禁用这种便利性,并且没有默认库(如果您正在做一些不寻常的事情并且不想要它们)。非默认库,您必须告诉链接器使用它们。
有一种机制可以告诉源代码中需要哪些库(包含文件是纯文本,只是在 #include 行“复制粘贴”),没有技术困难。但就是没有(据我所知,甚至没有非标准编译器扩展)。 这个问题有一些解决方案,例如用于unixy平台的
pkg-config,它通过轻松地为库提供编译器和链接器选项来解决包含文件和库文件的问题。