Linux中对pthread_create的未定义引用

我从https://computing.llnl.gov/tutorials/pthreads/的网页上得到了下面的演示

#include <pthread.h>
#include <stdio.h>
#define NUM_THREADS     5


void *PrintHello(void *threadid)
{
long tid;
tid = (long)threadid;
printf("Hello World! It's me, thread #%ld!\n", tid);
pthread_exit(NULL);
}


int main (int argc, char *argv[])
{
pthread_t threads[NUM_THREADS];
int rc;
long t;
for(t=0; t<NUM_THREADS; t++){
printf("In main: creating thread %ld\n", t);
rc = pthread_create(&threads[t], NULL, PrintHello, (void *)t);
if (rc){
printf("ERROR; return code from pthread_create() is %d\n", rc);
exit(-1);
}
}
pthread_exit(NULL);
}

但是当我在我的机器上编译它时(运行Ubuntu Linux 9.04),我得到以下错误:

corey@ubuntu:~/demo$ gcc -o term term.c
term.c: In function ‘main’:
term.c:23: warning: incompatible implicit declaration of built-in function ‘exit’
/tmp/cc8BMzwx.o: In function `main':
term.c:(.text+0x82): undefined reference to `pthread_create'
collect2: ld returned 1 exit status

这对我来说没有任何意义,因为头文件包括pthread.h,它应该有pthread_create函数。知道哪里出了问题吗?

892601 次浏览

对于Linux,正确的命令是:

gcc -pthread -o term term.c

一般来说,库应该在命令行上遵循源和对象,而-lpthread不是一个“选项”,它是一个库规范。在只安装了libpthread.a的系统上,

gcc -lpthread ...

将无法链接。

你需要在gcc中使用选项-lpthread

你只需要在属性中添加“pthread”=>C/ c++ build=>GCC c++连接器=>Libraries=>顶部部分“Libraries(-l)”。

在eclipse中

属性->c/c++构建->设置->GCC c++连接器->库在顶部添加“pthread”

在Anjuta中,进入构建菜单,然后配置项目。 2 .在“配置选项”中添加:

LDFLAGS='-lpthread'

希望它也能帮助到别人…

有时,如果您使用多个库,请检查库依赖关系。 (例如:-lpthread -lSDL…& lt; = = >…-lSDL -lpthread) < / p >

实际上,如果你继续阅读下面的教程,它给出了几个用于pthreads代码的编译命令示例,如下表所示:

< a href = " https://computing.llnl.gov/tutorials/pthreads/编译" > https://computing.llnl.gov/tutorials/pthreads/编译< / >

enter image description here

像这样编译:gcc demo.c -o demo -pthread

如果你正在使用cmake,你可以使用:

add_compile_options(-pthread)

SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthread")

从Linux终端运行,对我来说有用的是使用以下命令进行编译(假设我想编译的c文件名为test.c):

gcc -o test test.c -pthread

希望它能帮助到一些人!

对于Linux,正确的命令是:

gcc -o term term.c -lpthread
  1. 你必须把-lpthread放在compile命令之后,这个命令会告诉编译器使用pthread.h库执行程序。
  2. GCC -l链接一个库文件。链接带库名且不带lib前缀的-l。

检查手册页,您将得到。

使用-pthread编译和链接。

SYNOPSIS
#include <pthread.h>


int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
void *(*start_routine) (void *), void *arg);




Compile and link with -pthread.
....

在Visual Studio 2019中,在项目的属性页中指定-pthread:

链接器->命令行->附加选项

在文本框中输入-pthread

我认为在CMake中添加pthread的正确方法如下

find_package (Threads REQUIRED)


target_link_libraries(helloworld
${CMAKE_THREAD_LIBS_INIT}
)

因为没有一个答案能完全满足我的需求(使用MSVS代码),我在这里添加了我使用这个IDE和CMAKE构建工具的经验。

第一步:确保在你的。cpp(或。hpp,如果需要)中包含:

#include <functional>

步骤2 MSVSCode IDE用户: 将这一行添加到你的< >强c_cpp_properties.json < / >强文件:

"compilerArgs": ["-pthread"],

将这一行添加到您的c_cpp_properties。/></a> . Json文件</p>
对于CMAKE构建工具用户:
将这一行添加到<em>< >强CMakeLists.txt < / >强</em></p>
<pre><code>set(CMAKE_CXX_FLAGS "-pthread")
</code></pre>
<p>注意:添加标志<em>-lpthread</em>(而不是<em>pthread</em>)会导致链接失败。</p></div>
                                                                            </div>
                                </div>
                            </div>
                        </div>
                                                <div class=

man gcc,

  -pthread
Define additional macros required for using the POSIX threads library.
You should use this option consistently for both compilation and linking.
This option is supported on GNU/Linux targets,
most other Unix derivatives,
and also on x86 Cygwin and MinGW targets.

-pthread是一个选项,也是处理这个问题的最佳方式,这是正确的。 在一些答案中,有一些语句表示它生成了不同的编译代码。

如果你想复制-pthread,你可以使用-lpthread -D_REENTRANT=1。因此,-pthread选项有两件事要做。

实际上,正如许多答案所表达的那样,它与pthread库链接。此外,pthread库的顺序也很重要,因为它可能会覆盖一些弱符号。因此,使用-lpthread的正确版本可能需要在命令行上多次使用它。

另一个重要的部分是_REENTRANT定义。注意,这是在实现名称空间中。一些人可能关心便携性,而另一些人则不然。但是,将它定义为编译单元中的第一个内容是非常重要的。这个符号将改变许多系统头文件的解析方式。

你可以在每个源文件的顶部包含#define _REENTRANT 1,但是在命令行中包含它要容易得多。同样,-pthread是实现这一点的最佳方法。而且,gcc将来可能会改变实现的方式。然而,我认为对程序员来说,理解正在发生的事情是很重要的。


term.c:在函数' main ': term.c:23:警告:不兼容隐式 内置函数' exit '的声明

你从来没有包括<stdlib.h>,在那里声明了exit()。另外,我认为gcc的新版本已经消除了对_REENTRANT的需求。

因此,它是生成不同的代码。即,编译器的后端是不同。它只是条件编译和链接到不同的库。它不会生成“无锁”代码或添加适当的机器屏障,因为您已经使用了这个选项。