转载地址:https://blog.csdn.net/skylinethj/article/details/38569243
在编译多线程程序时遇到了
undefined reference to `pthread_create'
在网上找了很多都说加上编译开关-lpthread
但是问题没有解决,后来找到下面的一篇博文才知道问题所在...
在编译下面的代码时,碰到了undefined reference to `pthread_atfork'的错误:
代码来自《POSIX多线程程序设计》
- /*
- * atfork.c
- * Demonstrate the use of "fork handlers" to protect data invariants across a fork.
- */
- #include
- #include
- #include
- #include "errors.h"
-
- pid_t self_pid; /* pid of current process */
- pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
-
- void fork_prepare(void)
- {
- pthread_mutex_lock(&mutex);
- }
-
- void fork_parent(void)
- {
- pthread_mutex_unlock(&mutex);
- }
-
- void fork_child(void)
- {
- self_pid = getpid();
- pthread_mutex_unlock(&mutex);
- }
-
- void *thread_routine(void *arg)
- {
- pid_t child_pid;
-
- child_pid = fork();
- if(child_pid == (pid_t)-1)
- errno_abort("Fork");
-
- pthread_mutex_lock(&mutex);
- pthread_mutex_unlock(&mutex);
- printf("After fork: %d (%d)\n", child_pid, self_pid);
- if(child_pid != 0){ // parent process
- if ((pid_t)-1 == waitpid(child_pid, (int*)0, 0))
- errno_abort("Wait for child");
- }
- return NULL;
- }
-
- int main(int argc, char *argv[])
- {
- pthread_t fork_thread;
- int atfork_flag = 1;
-
- if(argc > 1)
- atfork_flag = atoi (argv[1]);
- if(atfork_flag){
- pthread_atfork(fork_prepare, fork_parent, fork_child);
- }
- self_pid = getpid();
- pthread_mutex_lock(&mutex);
-
- pthread_create(&fork_thread, NULL, thread_routine, NULL);
- sleep(5);
- pthread_mutex_unlock (&mutex);
- pthread_join(fork_thread, NULL);
-
- return 0;
- }
编译运行结果:
- digdeep@ubuntu:~/pthread/learnthread$ gcc -Wall -lpthread -o atfork atfork.c /tmp/cckSrItT.o: In function `main':
- atfork.c:(.text+0x195): undefined reference to `pthread_atfork'
- collect2: ld returned 1 exit status
- digdeep@ubuntu:~/pthread/learnthread$ gcc -Wall -pthread -o atfork atfork.c
- digdeep@ubuntu:~/pthread/learnthread$ ./atfork
- After fork: 2637 (2635)
- After fork: 0 (2637)
- digdeep@ubuntu:~/pthread/learnthread$
于是想搞清楚 -lpthread和-pthread的区别:
- digdeep@ubuntu:~$ gcc --version
- gcc (Ubuntu/Linaro 4.5.2-8ubuntu4) 4.5.2
- Copyright (C) 2010 Free Software Foundation, Inc.
- This is free software; see the source for copying conditions. There is NO
- warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-
- digdeep@ubuntu:~$ man gcc | grep pthread
- -mvxworks -G num -pthread
- -mno-unaligned-doubles -mv8plus -mno-v8plus -mvis -mno-vis -threads -pthreads
- -pthread
- implies -pthread, and thus is only supported on targets that have support for
- -pthread.
- implies -pthread, and thus is only supported on targets that have support for
- -pthread.
- option and the -pthread option are incompatible.
- -pthread
- Adds support for multithreading with the pthreads library. This option sets flags for
- -pthreads
- -pthread
- This is a synonym for -pthreads.
- digdeep@ubuntu:~$
- digdeep@ubuntu:~$ man gcc | grep lpthread
- digdeep@ubuntu:~$
- digdeep@ubuntu:~$
从上面的输出可以看到,目前gcc 4.5.2中已经没有了关于 -lpthread的介绍了。所以以后的多线程编译应该用
-pthread,而不是-lpthread。
仔细的阅读man gcc中的关于pthread的介绍:
- -pthread
- Adds support for multithreading with the pthreads library. This option sets flags for
- both the preprocessor and linker.
-
- -pthreads
- Add support for multithreading using the POSIX threads library. This option sets
- flags for both the preprocessor and linker. This option does not affect the thread
- safety of object code produced by the compiler or that of libraries supplied with it.
-
- -pthread
- This is a synonym for -pthreads.
从上面的 man gcc中的详细说明可以看出:
1)-pthread和-pthreads的含义是相同的。
2)-pthread或者-pthreads的编译选项是用于在编译时增加多线程的支持。该选项同时对“预处理器”和“链接器”产
生作用。
3)-pthread或者-pthreads的编译选项,即不影响编译器产生的目标代码的线程安全性,也不影响对提供的支持
多线程的函数库libraries(的选择).(gcc 会自动链接系统当前版本推荐的 thread lib 以及对应的 thread
safe 的 c func。 http://kasicass.blog.163.com/blog/static/395619200992410313759/)
但是,下面的输出却又说明,我们不能使用 -pthreads:
- digdeep@ubuntu:~/pthread/learnthread$ gcc -Wall -pthreads -o atfork atfork.c
- gcc: unrecognized option '-pthreads'
- /tmp/ccZZmWbD.o: In function `main':
- atfork.c:(.text+0x195): undefined reference to `pthread_atfork'
- atfork.c:(.text+0x1cf): undefined reference to `pthread_create'
- atfork.c:(.text+0x1fb): undefined reference to `pthread_join'
- collect2: ld returned 1 exit status
所以:一句话,我们现在应该使用 -pthread 而不是 -lpthread。
另:下面的英文文档详细说明了相关的情况。
http://gcc.gnu.org/onlinedocs/libstdc++/manual/using_concurrency.html
该文档的摘要:
When you link a multithreaded application, you will probably need to add a library or flag to g++. This is a very non-standardized area of GCC across ports. Some ports support a special flag (the spelling isn't even standardized yet) to add all required macros to a compilation (if any such flags are required then you must provide the flag for all compilations not just linking) and link-library additions and/or replacements at link time. The documentation is weak. Here is a quick summary to display how ad hoc this is: On Solaris, both -pthreads and -threads (with subtly different meanings) are honored. On OSF, -pthread and -threads (with subtly different meanings) are honored. On Linux/i386, -pthread is honored. On FreeBSD, -pthread is honored. Some other ports use other switches. AFAIK(就我所知), none of this is properly documented anywhere other than in ``gcc -dumpspecs'' (look at lib and cpp entries).
下面是摘录自命令 gcc -dumpspecs的输出:
- *cpp:
- %{posix:-D_POSIX_SOURCE} %{pthread:-D_REENTRANT}
-
- *lib:
- %{pthread:-lpthread} %{shared:-lc} %{!shared:%{mieee-fp:-lieee} %{profile:-lc_p}%{!profile:-lc}}
%{pthread:-lpthread} 与上面的说明有点矛盾!!有点糊涂了。