使用 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
undefined reference to `pthread_create' Error when making C++11 application with ASIO and std::thread
提问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_STANDALONE
and so on in C/C++ General Symbols, and I expect that the ASIO header will use std::thread
instead of pthread
. However, I still see Error from make:
我还在ASIO_HAS_STD_THREAD, ASIO_STANDALONE
C/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_THREAD
but not ASIO_HAS_PTHREADS
, the posix_thread.ipp
should 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_PTHREADS
,posix_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 -pthread
and I have tried to compile a simple project without -pthread
in Eclipse. However, you can correct me if I am wrong. When I put -pthread
in the linker option, it does compile, however I felt I don't want the pthread if not necessary.
与大多数人认为的相反,C++11 不需要Eclipse -pthread
,我尝试在没有-pthread
Eclipse 的情况下编译一个简单的项目。但是,如果我错了,您可以纠正我。当我-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 pthread
library. It needs to link that
library if it requires Posix threads.
程序是用 C++11 编写的这一事实与它是否需要与pthread
库链接无关。如果需要 Posix 线程,则需要链接该库。
C++11 provides the std::thread
class 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::thread
objects 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 libpthread
by default. E.g. if your example program is in thread.cpp
I
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 libpthread
unless 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.hpp
states that if ASIO_HAS_THREAD_KEYWORD_EXTENSION
is defined, it doesn't need pthread. After I defined this in symbols, the make errors dropped by half, indicating, only the signal_blocker.hpp
is 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)
}