未定义的引用'pthread_create' – 链接器命令选项顺序(库之前/之后的对象文件?)
当我尝试编译时,我收到一个特定的错误。 但是,这是不可能的,因为我使用正确的标志。 在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
链接命令包含源文件时,请在libaries之前列出源文件和目标文件(如果有)。 因此, -l
选项位于命令行的末尾。 指定find库的相关-L
选项应位于指定库的-l
选项之前。
附属问题是:
为什么它工作?
当C编译器调用链接器时,它会告诉链接器将一些名称为crt0.o
系统对象文件提取出来,并告诉它寻找一个符号main
(或可能是_main()
,这取决于本地命名约定)。 它还按照您在命令行上指定的顺序提供对象文件和库。 当遇到目标文件时,链接器会logging它提供的定义以及它所做的不满意的引用。 当它遇到一个图书馆,它扫描图书馆,看它是否能满足任何不满意的参考。 如果图书馆可以提供任何尚未满足的参考资料,那么它包括图书馆(在可执行文件中)的相关部分。 对于共享库,链接器确保库在运行时被加载。 对于静态库,链接器包含库中的至less满足一个引用的对象文件,重新扫描直到没有可以满足的更多引用。 如果库不满足引用,则忽略它。 当过程完成时,如果任何引用仍然不满意,您会收到错误消息。
所以,在你的场景中,你已经在Server1.o
或Util.o
之前使用了-lpthread
。 由于-lpthread
不提供main
function,这是唯一的相关不满意的符号,它被忽略。 math库-lm
也可能被忽略,或者它可能是一个空的存根,为其他math库与主C库分离的系统devise代码。 然后链接器读取您的对象文件,并find对pthread_create()
的引用。 之后当它扫描C库-lc
( libc.so
)时,发现符号满足除pthread_create
之外的所有内容。
当这些库在对象文件之后列出时,链接器在扫描-lpthread
时知道它需要pthread_create
,并确保在运行时加载共享库。
GNU ld
和--as-needed
选项
上面的讨论基本上是平台中立的。 如果您按照“对象文件之后的库”规则,则链接器行在所有平台上都有最大可能正常工作。
如果您使用的是GNU binutils
软件包,特别是GNU ld
命令,则可能会发现不同的行为。
来自Sourceware的手册(如果您尝试使用http://www.gnu.org/software/binutils/manuals ,则是您redirect的地方)包含以下信息:
--as-needed
--no-as-needed
此选项会影响在--as-needed
选项之后在命令行中提到的dynamic库的ELF DT_NEEDED标记。 通常,链接器将为命令行中提到的每个dynamic库添加一个DT_NEEDED标记,而不pipe该库是否实际需要。--as-needed
会导致DT_NEEDED标记仅针对链接中的某个库满足来自常规对象文件的非弱定义符号引用的库,或者如果在其他DT_NEEDED列表中找不到该库库,来自另一个dynamic库的非弱的未定义符号引用。 在问题库之后,在命令行上出现的对象文件或库不会影响库是否被视为需要。 这与从档案中提取目标文件的规则类似。--no-as-needed
恢复默认行为。
看来不同版本的不同系统使用不同的值as-needed
选项。 尽pipe“ --no-as-needed
行为是非常方便的,因为它允许您在命令行上以或多或less顺序排列库和对象文件,这也意味着命令行上列出的所有库在运行时都会加载,即使从库中没有实际使用的符号(因此--no-as-needed
就相当于一个假设的--whether-needed-or-not
标志)。 使用--as-needed
选项是经典和可移植的行为。
有传言说,有些Linux发行版在过去的5年左右(第三个千年的第二个十年的前半部分)将其系统中的默认行为从“ --no-as-needed
改为“ --as-needed
”争论的缘故)。 你可以在SO的许多问题上find支持这个谣言的证据。
编译时使用-pthread。 试试看,你会解决你的问题