Undefined reference to `pthread_create 'Error creating C ++ 11 application with ASIO and std :: thread

I installed Eclipse (actually the Xilinx SDK, but based on Eclipse) and g ++ 4.9.2, to compile a project that uses stand-alone ASIO, and I used -std = C ++ 11 in Properties -> C / C ++ Build -> Settings -> Tool settings β†’ Other flags so that it can be compiled using all the features of C ++ 11.

I also set ASIO_HAS_STD_THREAD, ASIO_STANDALONE , etc. in common C / C ++ characters, and I expect the ASIO header to use std::thread instead of pthread . However, I still see Error from 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 that I am using C ++ 11 and ASIO_HAS_STD_THREAD is ASIO_HAS_STD_THREAD , but not ASIO_HAS_PTHREADS , posix_thread.ipp should not even be enabled (via posix_thread.hpp), according to thread.hpp in ASIO:

 #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

Unlike most people, C ++ 11 does not need -pthread , and I tried to compile a simple project without -pthread in Eclipse. However, if I am mistaken, you can correct me. When I put -pthread into the linker option, it compiles, however I felt that I didn’t need pthread if not needed.

Suspect 2 - ASIO File

When I look through posix_tss_ptr.hpp, I also found in Makefile.am. I wonder if this affects the error?

So what is the cause of the problem? If not above two suspects? I hope the solution can still use the clean C ++ 11 method, rather than using pthread if my reasoning is correct.

Update

I found that ASIO_HAS_PTHREADS is not determined by me and why ASIO uses POSIX streams somewhere, but the linker needs the -pthread option. Then I traced to asio / detail / signal_blocker.hpp using the #error directive. There are only two places that they are defined and they are in 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 is still responding to POSIX THREADS or Windows for signal_blocker.hpp shown below. This is why ASIO still needs 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 determined from the gnu cross-compiler (arm-xilinx-linux-gnueabi), including files like features.h, posix_opt.h, etc. I'm not going to keep track of what the macro really defined, but ASIO is the source that uses _POSIX_THREADS, and therefore there must be a -pthread linker option.

Again, non ASIO C ++ 11 thread is not needed -pthread for g ++ 4.9.2, but stand-alone ASIO needs it. The following code is built correctly without -pthread in g ++ 4.9.2 (Xilinx SDK based on Eclipse):

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

The fact that the program is written in C ++ 11 is not related to the fact that you do not need to associate it with the pthread library. You must link these libraries if you need Posix streams for this.

C ++ 11 provides the std::thread class, and each corresponding compiler standard, the library must implement the functionality of this class using the thread APIs hosted by the target system. GCC implements it with pthreads , so you cannot create a program that creates std::thread objects with GCC unless you associate it with -pthread . This fact is not related to asio .

LATER

I actually created a program without pthread using std :: std, just using -std = C ++ 11

I think you are mistaken and confused by the fact that some ports of Windows GCC link libpthread by default. For instance. if your sample program is in thread.cpp I can successfully create it on Windows with TDM-GCC 4.9.2 so that:

 >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 large number of library parameters are passed to the linker behind the scenes, in particular -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 bind libpthread unless you ask:

 $ 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 
+7
source

1. std :: thread not required -pthread

Here is what I dug from ASIO, and let me show you a simple example first. On CentOS 6.5 32 bit and in Eclipse using g ++ 4.9.3, the following code only builds with -std = C ++ 11, no need to specify -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 () to main, it fails with an undefined reference to `pthread_create '

 void *PrintHello(void *threadid) { long tid; tid = (long)threadid; std::cout<<"Hello World! It 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 dependency on -pthread

First, there is code in standalone ASIO that uses posix thread, but can also use std. The order must be reordered to use std first when both are defined. Sample code from the string 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" 

Secondly, there are two more files that need posix: signal_blocker.hpp and tss_ptr.hpp. The error will be executed because only Windows and POSIX are supported.

I do not know if it is possible to completely rewrite two files to use C ++ 11, but these two files are a source of dependency on -lpthread, not std :: thread.

Update

tss_ptr.hpp indicates that if ASIO_HAS_THREAD_KEYWORD_EXTENSION defined, it does not need pthread. After I defined this in characters, make errors were halved, indicating that only the source of signal_blocker.hpp is the source of this dependency.

affects 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

 { #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) } 
+1
source

During the exclusion of using g ++ ssss code (your code name) .cpp -std = C ++ 11 -pthread

he will work

0
source

Source: https://habr.com/ru/post/1241164/


All Articles