编译Linux程序出现“对‘pthread_create’未定义的引用”

  在学习Linux程序设计POXIS线程的时候,编译一个段简单的代码,就出现下面的错误:

1 /tmp/cc2FQJTh.o:在函数‘main’中:
2 1-thread.c:(.text+0x29):对‘pthread_create’未定义的引用
3 1-thread.c:(.text+0x67):对‘pthread_join’未定义的引用
4 collect2: 错误: ld 返回 1

  可是在我的代码中已经包含了pthread.h,这是什么回事呢,百度一下,发现网上大部分的解决办法是在gcc编译命令加上选项:lpthread。

1 gcc -o pthread -lpthread pthread.c

  但我照着网上的方法试试,发现还是不行,错误提示与原来相同。后来才发现是我自己错了,我是在目标代码文件前加上-lpthread。但实际的做法应该是在代码文件后面添加此选项。

复制代码
1 finlay@finlay-Lenovo-G470:~/文档/程序设计/Linux程序设计/12章$ gcc 1-thread.c -lpthread
2 #成功!
3 finlay@finlay-Lenovo-G470:~/文档/程序设计/Linux程序设计/12章$ gcc -lpthread -Wall 1-thread.c
4 #失败!
5 /tmp/ccE6dosW.o:在函数‘main’中:
6 1-thread.c:(.text+0x29):对‘pthread_create’未定义的引用
7 1-thread.c:(.text+0x67):对‘pthread_join’未定义的引用
8 collect2: 错误: ld 返回 1
复制代码

  但是还有一个什么有趣的现象,如下:

复制代码
1 finlay@finlay-Lenovo-G470:~/文档/程序设计/Linux程序设计/12章$ gcc -pthread 1-thread.c
2 #成功!
3 finlay@finlay-Lenovo-G470:~/文档/程序设计/Linux程序设计/12章$ gcc -lpthread 1-thread.c
4 #失败!
5 /tmp/ccbr6m7v.o:在函数‘main’中:
6 1-thread.c:(.text+0x29):对‘pthread_create’未定义的引用
7 1-thread.c:(.text+0x67):对‘pthread_join’未定义的引用
8 collect2: 错误: ld 返回 1
复制代码

  那么,-pthread与-lpthread的区别是什么呢?我们可以在verbose模式下执行一下对应的gcc命令行看出来。下面是老式的直接加 -lpthread 链接选项的输出结果:

复制代码
$ gcc -v -c x.c
...
/usr/lib/gcc/i486-linux-gnu/4.2.4/cc1 -quiet -v x.c -quiet -dumpbase x.c
-mtune=generic -auxbase x -version -fstack-protector -fstack-protector -o /tmp/cch4ASTF.s
...
as --traditional-format -V -Qy -o x.o /tmp/cch4ASTF.s
...
$ gcc -v x.o -ox -lpthread
...
 /usr/lib/gcc/i486-linux-gnu/4.2.4/collect2 --eh-frame-hdr -m elf_i386 --hash-style=both
-dynamic-linker /lib/ld-linux.so.2 -ox
/usr/lib/gcc/i486-linux-gnu/4.2.4/../../../../lib/crt1.o
/usr/lib/gcc/i486-linux-gnu/4.2.4/../../../../lib/crti.o
/usr/lib/gcc/i486-linux-gnu/4.2.4/crtbegin.o
-L/opt/intel/Compiler/11.1/046/tbb/ia32/cc4.1.0_libc2.4_kernel2.6.16.21/lib/../lib
-L/usr/lib/gcc/i486-linux-gnu/4.2.4
-L/usr/lib/gcc/i486-linux-gnu/4.2.4
-L/usr/lib/gcc/i486-linux-gnu/4.2.4/../../../../lib
-L/lib/../lib
-L/usr/lib/../lib
-L/opt/intel/Compiler/11.1/046/lib/ia32
-L/opt/intel/Compiler/11.1/046/tbb/ia32/cc4.1.0_libc2.4_kernel2.6.16.21/lib
-L/usr/lib/gcc/i486-linux-gnu/4.2.4/../../..
x.o -lpthread -lgcc --as-needed -lgcc_s --no-as-needed -lc -lgcc
--as-needed -lgcc_s --no-as-needed
/usr/lib/gcc/i486-linux-gnu/4.2.4/crtend.o /usr/lib/gcc/i486-linux-gnu/4.2.4/../../../../lib/crtn.o
复制代码

  下面是在编译和链接时分别指定 -pthread 选项的输出结果:

复制代码
 1 $ gcc -v -pthread -c x.c
 2 ...
 3 /usr/lib/gcc/i486-linux-gnu/4.2.4/cc1 -quiet -v -D_REENTRANT
 4  x.c -quiet -dumpbase x.c
 5 -mtune=generic -auxbase x -version -fstack-protector -fstack-protector -o /tmp/cc205IQf.s
 6 ...
 7 as --traditional-format -V -Qy -o x.o /tmp/cc205IQf.s
 8 ...
 9 $ gcc -v x.o -ox -pthread
10 /usr/lib/gcc/i486-linux-gnu/4.2.4/collect2 --eh-frame-hdr -m elf_i386 --hash-style=both
11 -dynamic-linker /lib/ld-linux.so.2 -ox
12 /usr/lib/gcc/i486-linux-gnu/4.2.4/../../../../lib/crt1.o
13 /usr/lib/gcc/i486-linux-gnu/4.2.4/../../../../lib/crti.o
14 /usr/lib/gcc/i486-linux-gnu/4.2.4/crtbegin.o
15 -L/opt/intel/Compiler/11.1/046/tbb/ia32/cc4.1.0_libc2.4_kernel2.6.16.21/lib/../lib
16 -L/usr/lib/gcc/i486-linux-gnu/4.2.4
17 -L/usr/lib/gcc/i486-linux-gnu/4.2.4
18 -L/usr/lib/gcc/i486-linux-gnu/4.2.4/../../../../lib
19 -L/lib/../lib
20 -L/usr/lib/../lib
21 -L/opt/intel/Compiler/11.1/046/lib/ia32
22 -L/opt/intel/Compiler/11.1/046/tbb/ia32/cc4.1.0_libc2.4_kernel2.6.16.21/lib
23 -L/usr/lib/gcc/i486-linux-gnu/4.2.4/../../..
24 x.o -lgcc --as-needed -lgcc_s --no-as-needed -lpthread
25  -lc -lgcc
26 --as-needed -lgcc_s --no-as-needed
27 /usr/lib/gcc/i486-linux-gnu/4.2.4/crtend.o /usr/lib/gcc/i486-linux-gnu/4.2.4/../../../../lib/crtn.o
复制代码

  所以可见编译选项中指定 -pthread 会附加一个宏定义 -D_REENTRANT ,该宏会导致 libc 头文件选择那些thread-safe的实现;链接选项中指定 -pthread 则同 -lpthread 一样,只表示链接 POSIX thread 库。由于 libc 用于适应 thread-safe 的宏定义可能变化,因此在编译和链接时都使用 -pthread 选项而不是传统的 -lpthread 能够保持向后兼容,并提高命令行的一致性。

你可能感兴趣的:(Unix/Linux)