编译时 -pthread 和 -lpthread 之间的区别

Posted

技术标签:

【中文标题】编译时 -pthread 和 -lpthread 之间的区别【英文标题】:Difference between -pthread and -lpthread while compiling 【发布时间】:2014-06-08 16:10:09 【问题描述】:

编译多线程程序时使用的gcc -pthreadgcc -lpthread有什么区别?

【问题讨论】:

Significance of -pthread flag when compiling的可能重复 【参考方案1】:

-pthread 告诉编译器链接到 pthread 库以及配置线程的编译。

例如,以下显示了在我的 Ubuntu 机器上安装的 GCC 包上使用 -pthread 选项时定义的宏:

$ gcc -pthread -E -dM test.c > dm.pthread.txt
$ gcc          -E -dM test.c > dm.nopthread.txt
$ diff dm.pthread.txt dm.nopthread.txt 
152d151
< #define _REENTRANT 1
208d206
< #define __USE_REENTRANT 1

使用 -lpthread 选项只会导致 pthread 库被链接 - 未定义预定义的宏。

底线:您应该使用-pthread 选项。


注意:-pthread 选项在 GCC 文档中被记录为特定于平台的选项,因此它可能并不总是可用。但是,它可在 GCC 文档未明确列出的平台上使用(例如 i386 和 x86-64) - 您应该在可用时使用它。

另请注意,GCC 使用了其他类似的选项,例如 -pthreads(在 Solaris 2 上列为 -pthread 的同义词)和 -mthread(用于 i386 和 x86-64 上的 MinGW 特定线程支持视窗)。我的理解是,GCC 正试图继续使用-pthread

【讨论】:

这很奇怪,因为它直接与 POSIX 相矛盾。 POSIX 要求通过 -lpthread 就足以获得整个 POSIX 线程库。 @FUZxxl 传递 -lpthread 确实 获得整个 POSIX 线程库。 @immibis 不,我的意思是,POSIX 说与-lpthread 链接应该足以获得完整的 pthread 支持。不需要其他编译标志。 @alecov POSIX 规定,如果您配置 POSIX 环境并与 -lpthread 链接,则 pthread 必须工作。但是,gcc 文档表明这可能不足以获得 pthreads 支持,这是我通过之前的 cmets 提出的观点。如果您不提供-lpthread 或其他一些随机的专有选项,我根本不关心会发生什么。 POSIX 仅指定 -lpthread 来保证 pthreads,而 gcc 似乎还不够。【参考方案2】:

有一个公认的答案,但是,IMO,它没有提供足够的背景和洞察力。因此,这个额外的答案。


-lpthread 是一个不再存在的问题的解决方案(自~2005 年以来)。

在过去,Pthreads API 的专有实现不符合 POSIX,例如 LinuxThreads。 POSIX 标准只是说,如果一个人想要符合 POSIX 的行为,那么必须与-lpthread 链接,并且链接是链接符合 POSIX 的 Pthreads API 实现所需的链接,应该有 它的多个实现

现代操作系统中没有 Pthreads API 的多种实现。这就是为什么-lpthread 不再有任何用途的原因。


gccclang 这样的编译器(可能还有所有与Linux 兼容的编译器)需要 使用-pthread 命令行选项来编译和链接符合POSIX 的多线程应用程序这是必须使用的。

编译器的文档是最终的权威来源,任何不同的第 3 方文档都是无关紧要的。

在编译时,-pthread 选项表明请求了 Pthread API(可以有多个线程 API,例如 Solaris 线程)并定义特定于平台的宏(_REENTRANT on Linux、_MT 在 Solaris 上)。

在链接时,-pthread 链接到实现符合 POSIX 标准的 Pthreads API 行为的所需库(如果有)中。

以上说明了为什么-lpthread既非必要也不充分。


GNU libc 2.34:

新应用程序不再需要与-lpthread-ldl-lutil-lanl 链接。为了向后兼容,提供了空的静态存档libpthread.alibdl.alibutil.alibanl.a,以便链接器选项继续工作。与 glibc 2.33 或更早版本链接的应用程序继续加载相应的共享对象(现在为空)。

【讨论】:

【参考方案3】:

-pthread 通过 pthreads 库添加对多线程的支持。此选项为预处理器和链接器设置标志 (man gcc)。

同时

-lpthread 在链接时存在,在预处理时不会受到影响。

【讨论】:

以上是关于编译时 -pthread 和 -lpthread 之间的区别的主要内容,如果未能解决你的问题,请参考以下文章

编译时和运行时OC中对象的动态编译机制

CODEBLOCKS10.05 编译运行时 DOS窗口的中文显示为乱码?怎么解决?

Java编译时类型和运行时类型的区别

请教一些Nodejs 编译安装时遇到的问题

Gradle 中编译和运行时配置的区别

请教一些Nodejs 编译安装时遇到的问题