使用 ASIO 和 std::thread 制作 C++11 应用程序时对“pthread_create”的未定义引用错误

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/34933042/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 14:27:23  来源:igfitidea点击:

undefined reference to `pthread_create' Error when making C++11 application with ASIO and std::thread

c++c++11pthreadsstdthread

提问by Splash

I set Eclipse (Actually Xilinx SDK but based on Eclipse), and g++4.9.2, to compile a project which uses standalone ASIO and I used -std=c++11 in the Properties -> C/C++ Build -> Settings -> Tool Settings -> Other flags so it can compile using all C++11 features.

我设置了 Eclipse(实际上是 Xilinx SDK,但基于 Eclipse)和 g++4.9.2,来编译一个使用独立 ASIO 的项目,我在 Properties -> C/C++ Build -> 中使用了 -std=c++11设置 -> 工具设置 -> 其他标志,以便它可以使用所有 C++11 功能进行编译。

I also set ASIO_HAS_STD_THREAD, ASIO_STANDALONEand so on in C/C++ General Symbols, and I expect that the ASIO header will use std::threadinstead of pthread. However, I still see Error from make:

我还在ASIO_HAS_STD_THREAD, ASIO_STANDALONEC/C++ 通用符号中设置等等,我希望 ASIO 标头将使用std::thread而不是pthread. 但是,我仍然看到来自 make 的错误:

undefined reference to pthread_create, 
..asio-1.10.6\include\asio\detail\impl\posix_thread.ipp
and posix_tss_ptr.hpp

so the problem is, since I am using C++11, and specified ASIO_HAS_STD_THREADbut not ASIO_HAS_PTHREADS, the posix_thread.ippshould not be even included (through posix_thread.hpp), according to thread.hpp in ASIO:

所以问题是,根据 ASIO 中的 thread.hpp ,由于我使用的是 C++11,并且指定ASIO_HAS_STD_THREAD但未指定ASIO_HAS_PTHREADSposix_thread.ipp甚至不应该包含(通过 posix_thread.hpp):

#if !defined(ASIO_HAS_THREADS)
# include "asio/detail/null_thread.hpp"
#elif defined(ASIO_WINDOWS)
# if defined(UNDER_CE)
#  include "asio/detail/wince_thread.hpp"
# else
#  include "asio/detail/win_thread.hpp"
# endif
#elif defined(ASIO_HAS_PTHREADS)
# include "asio/detail/posix_thread.hpp"
#elif defined(ASIO_HAS_STD_THREAD)
# include "asio/detail/std_thread.hpp"
#else
# error Only Windows, POSIX and std::thread are supported!
#endif

Suspect 1 -pthread

怀疑 1 -pthread

Contrary to most people believe, C++11 doesn't need the -pthreadand I have tried to compile a simple project without -pthreadin Eclipse. However, you can correct me if I am wrong. When I put -pthreadin the linker option, it does compile, however I felt I don't want the pthread if not necessary.

与大多数人认为的相反,C++11 不需要Eclipse -pthread,我尝试在没有-pthreadEclipse 的情况下编译一个简单的项目。但是,如果我错了,您可以纠正我。当我-pthread输入链接器选项时,它会编译,但是我觉得如果没有必要的话我不想要 pthread。

Suspect 2 - ASIO makefile

嫌疑人 2 - ASIO 生成文件

When I search the posix_tss_ptr.hpp, I found also in Makefile.am. I wonder whether this affect the error?

当我搜索 posix_tss_ptr.hpp 时,我也在 Makefile.am 中找到了。我想知道这是否会影响错误?

So what is the cause of the problem? If not the above two suspect? I hope the solution can be still using pure C++11 way, not to use pthread if my reasoning is correct.

那么问题的原因是什么?如果不是以上两个嫌疑人?我希望解决方案仍然可以使用纯 C++11 方式,如果我的推理正确,不要使用 pthread。

Update

更新

I found that ASIO_HAS_PTHREADS is defined not by me and that's why ASIO uses POSIX threads somewhere and the linker then needs the option -pthread. Then I traced down to the asio/detail/signal_blocker.hpp by using #error directive. There are only two places that it is defined and they are in ASIO config.hpp

我发现 ASIO_HAS_PTHREADS 不是由我定义的,这就是为什么 ASIO 在某处使用 POSIX 线程,然后链接器需要选项 -pthread。然后我使用 #error 指令追踪到 asio/detail/signal_blocker.hpp。它只定义了两个地方,它们在 ASIO config.hpp 中

#  if defined(ASIO_HAS_BOOST_CONFIG) && defined(BOOST_HAS_PTHREADS)
#   define ASIO_HAS_PTHREADS 1
#  elif defined(_POSIX_THREADS)
#   define ASIO_HAS_PTHREADS 1

ASIO still replies on POSIX THREADS or Windows for signal_blocker.hpp shown below. That's why ASIO still needs pthread.

ASIO 仍然在 POSIX THREADS 或 Windows 上回复如下所示的 signal_blocker.hpp。这就是为什么 ASIO 仍然需要 pthread。

#if !defined(ASIO_HAS_THREADS) || defined(ASIO_WINDOWS) \
  || defined(ASIO_WINDOWS_RUNTIME) \
  || defined(__CYGWIN__) || defined(__SYMBIAN32__)
typedef null_signal_blocker signal_blocker;
#elif defined(ASIO_HAS_PTHREADS)
typedef posix_signal_blocker signal_blocker;
#endif

And _PTHREADS is defined from the gnu cross compiler (arm-xilinx-linux-gnueabi) include files such as features.h, posix_opt.h, and etc. I am not going to track down which truly defined the macro, but ASIO is the source which uses _POSIX_THREADS and so the linker option -pthread should be there.

_PTHREADS 是从 gnu 交叉编译器 (arm-xilinx-linux-gnueabi) 定义的包含文件,例如 features.h、posix_opt.h 等。我不打算追踪哪个真正定义了宏,但 ASIO 是使用 _POSIX_THREADS 的源,因此链接器选项 -pthread 应该在那里。

Again, non ASIO C++11 thread doesn't need -pthread for g++ 4.9.2 but standalone ASIO needs it. The following code is built correctly without -pthread in g++4.9.2 (Xilinx SDK which is based on Eclipse):

同样,对于 g++ 4.9.2,非 ASIO C++11 线程不需要 -pthread,但独立的 ASIO 需要它。以下代码在 g++4.9.2(基于 Eclipse 的 Xilinx SDK)中没有 -pthread 的情况下正确构建:

#include <thread>
void test() {
    for(int i=0;i<100;i++);
}
int main()
{
    std::thread thread1(test);
    thread1.join();
    return 0;
}

回答by Mike Kinghan

The fact that a program is written in C++11 has no bearing on with whether or not it needs to be linked with the pthreadlibrary. It needs to link that library if it requires Posix threads.

程序是用 C++11 编写的这一事实与它是否需要与pthread库链接无关。如果需要 Posix 线程,则需要链接该库。

C++11 provides the std::threadclass and each conforming compiler's standard library must implement the functionality of that class using some native threads API hosted by the target system. GCC implements it using pthreads, so you cannot any build a program that creates std::threadobjects with GCC unless you link it with -pthread. This fact is unconnected with asio.

C++11 提供了std::thread类,每个符合标准的编译器的标准库都必须使用目标系统托管的一些本机线程 API 来实现该类的功能。GCC 使用 实现它pthreads,因此std::thread除非您将它与-pthread. 这个事实与 无关asio

LATER

之后

I actually built a program without pthread using std::std just using -std=c++11

我实际上使用 std::std 构建了一个没有 pthread 的程序,只是使用 -std=c++11

I think you are mistaken and confused by the fact that some Windows ports of GCC link libpthreadby default. E.g. if your example program is in thread.cppI can successfully build it in Windows with TDM-GCC 4.9.2 so:

我认为您对 GCC 的某些 Windows 端口libpthread默认链接这一事实感到误解和困惑。例如,如果您的示例程序在thread.cpp我可以使用 TDM-GCC 4.9.2 在 Windows 中成功构建它,所以:

>g++ -std=c++11 -o test_thread thread.cpp

But if you build it in verbose mode:

但是,如果您以详细模式构建它:

>g++ -v -std=c++11 -o test_thread thread.cpp

you can see that a great many library options are passed to the linker behind the scenes, in particular -lpthread:

你可以看到很多库选项在幕后传递给链接器,特别是-lpthread

>g++ -v -std=c++11 -o test_thread thread.cpp 2>&1 | grep -Po 'pass-through=-lpthread' -
pass-through=-lpthread

And on Linux you will not link libpthreadunless you ask:

在 Linux 上,libpthread除非你问,否则你不会链接:

$ g++ -std=c++11 -o test_thread thread.cpp
/tmp/ccpyEles.o: In function `std::thread::thread<void (&)()>(void (&)())':
thread.cpp:(.text._ZNSt6threadC2IRFvvEJEEEOT_DpOT0_[_ZNSt6threadC5IRFvvEJEEEOT_DpOT0_]+0x7d): undefined reference to `pthread_create'
collect2: error: ld returned 1 exit status

回答by Ramanand Yadav

During excution of code use g++ ssss(your code name).cpp -std=c++11 -pthread

在执行代码时使用 g++ ssss(your code name).cpp -std=c++11 -pthread

it will work

它会工作

回答by Splash

1. std::thread doesn't need -pthread

1. std::thread 不需要 -pthread

Here is what I dug out from ASIO, and let me show the simple example first. In CentOS 6.5 32 bit, and in Eclipse, using g++4.9.3, the following code builds with -std=c++11 only, no need to say -lpthread

下面是我从ASIO挖出来的,先举个简单的例子。在 CentOS 6.5 32 位和 Eclipse 中,使用 g++4.9.3,以下代码仅使用 -std=c++11 构建,无需说 -lpthread

std::string make_greeting_string()
{
    auto now = std::chrono::system_clock::now();
    const auto in_time_t = std::chrono::system_clock::to_time_t(now);

    std::stringstream ss;
    //ss << std::put_time(std::localtime(&in_time_t), "%Y-%m-%d %X");
    ss << "Greetings"<<45;
    return ss.str();
}
int main() {
    std::thread thread1(make_greeting_string);
    //test2();
    thread1.join();
    cout << "!!!Hello World!!!" << endl; // prints !!!Hello World!!!
    return 0;
}

Once I add tes2() in main, it fails with undefined reference to `pthread_create'

一旦我在 main 中添加了 tes2(),它就会失败,并没有定义对 `pthread_create' 的引用

void *PrintHello(void *threadid)
{
   long tid;
   tid = (long)threadid;
   std::cout<<"Hello World! It's me, thread #%ld!"<<tid<<std::endl;
   pthread_exit(NULL);
}


void test2()
{
    pthread_t threads[NUM_THREADS];
    int rc;
    long t;
    for(t=0;t<NUM_THREADS;t++){
        std::cout<<"In main: creating thread %ld"<<t<<std::endl;
        rc = pthread_create(&threads[t], NULL, PrintHello, (void *)t);
        if (rc){
            std::cout<<"ERROR; return code from pthread_create() is "<<rc<<std::endl;
            exit(-1);
        }
    }
}

2. Source of ASIO's dependency on -pthread

2、ASIO对-pthread的依赖来源

First, there are code in standalone ASIO which uses posix thread but can also use std. The order should be rearranged to use std first when both are defined. Code example from static_mutex.hpp line 27

首先,独立 ASIO 中的代码使用 posix 线程,但也可以使用 std。当两者都被定义时,应该重新排列顺序以首先使用 std。static_mutex.hpp 第 27 行的代码示例

#elif defined(ASIO_HAS_PTHREADS)  
#include "asio/detail/posix_static_mutex.hpp"
#elif defined(ASIO_HAS_STD_MUTEX_AND_CONDVAR)
#include "asio/detail/std_static_mutex.hpp"

Second, there are still two files that need posix: signal_blocker.hpp and tss_ptr.hpp. The make will fail because only Windows and POSIX are supported

其次,还有两个文件需要posix:signal_blocker.hpp和tss_ptr.hpp。make 会失败,因为只支持 Windows 和 POSIX

I don't know whether it's possible to completely rewrite the two files to use c++11, but these two files are the source of the dependency on -lpthread, not std::thread.

我不知道是否可以完全重写这两个文件以使用c++11,但这两个文件是-lpthread的依赖源,而不是std::thread。

update

更新

tss_ptr.hppstates that if ASIO_HAS_THREAD_KEYWORD_EXTENSIONis defined, it doesn't need pthread. After I defined this in symbols, the make errors dropped by half, indicating, only the signal_blocker.hppis the source of this dependency.

tss_ptr.hpp声明如果ASIO_HAS_THREAD_KEYWORD_EXTENSION已定义,则不需要 pthread。在我用符号定义它之后,make 错误减少了一半,表明只有signal_blocker.hpp是这种依赖关系的来源。

affects signal_set_service.ipp

影响signal_set_service.ipp

case asio::io_service::fork_child:
    if (state->fork_prepared_)
    {
      asio::detail::signal_blocker blocker;
      close_descriptors();
      open_descriptors();
      int read_descriptor = state->read_descriptor_;
      state->fork_prepared_ = false;
      lock.unlock();
      reactor_.register_internal_descriptor(reactor::read_op,
          read_descriptor, reactor_data_, new pipe_read_op);
    }
    break;

and select_reactor.ipp

和 select_reactor.ipp

{
#if defined(ASIO_HAS_IOCP)
  asio::detail::signal_blocker sb;
  thread_ = new asio::detail::thread(
      bind_handler(&select_reactor::call_run_thread, this));
#endif // defined(ASIO_HAS_IOCP)
}