关于C#:对” pthread_create”的未定义引用使用ASIO和std :: thread制作C 11应用程序时出错

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

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

我还在C / C通用符号中设置了ASIO_HAS_STD_THREAD, ASIO_STANDALONE,依此类推,我希望ASIO标头将使用std::thread而不是pthread。但是,我仍然看到来自make的错误:

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

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#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

嫌疑人1 -pthread

与大多数人相反,C 11不需要-pthread,我已经尝试在Eclipse中编译一个没有-pthread的简单项目。但是,如果我错了,您可以纠正我。当我将-pthread放在链接器选项中时,它确实可以编译,但是我觉得如果不需要,我不希望使用pthread。

可疑2-ASIO Makefile

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

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

更新

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

1
2
3
4
#  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仍在POSIX THREADS或Windows上针对以下所示的signal_blocker.hpp进行回复。这就是ASIO仍然需要pthread的原因。

1
2
3
4
5
6
7
#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

并且_PTHREADS是从gnu交叉编译器(arm-xilinx-linux-gnueabi)定义的,包括诸如features.h,posix_opt.h等文件。 ASIO是使用_POSIX_THREADS的源,因此应在其中使用链接器选项-pthread。

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

1
2
3
4
5
6
7
8
9
10
#include <thread>
void test() {
    for(int i=0;i<100;i++);
}
int main()
{
    std::thread thread1(test);
    thread1.join();
    return 0;
}

用C 11编写程序的事实与是否
它不需要与pthread库链接。它需要链接
库,如果它需要Posix线程。

C 11提供了std::thread类和每个符合标准的编译器标准
库必须使用某些本机实现该类的功能
目标系统托管的线程API。 GCC使用pthreads来实现它,
因此,您无法构建使用以下命令创建std::thread对象的程序
GCC,除非您将其与-pthread链接。此事实与asio无关。

LATER

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

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

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

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

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

您会看到很多库选项都传递给了链接器
在幕后,尤其是-lpthread

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

在Linux上,除非您询问以下内容,否则您将不会链接libpthread

1
2
3
4
$ 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


执行代码期间
g ssss(您的代码名称).cpp -std = c 11 -pthread

它将起作用


1. std :: thread不需要-pthread

这是我从ASIO中挖掘出来的内容,首先让我展示一个简单的示例。在CentOS 6.5 32位和Eclipse中,使用g 4.9.3,以下代码仅使用-std = c 11构建,而无需说-lpthread

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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;
}

一旦我在主目录中添加了tes2(),它就会失败,并带有对pthread_create的未定义引用。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
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. ASIO依赖于-pthread的来源

首先,独立的ASIO中有使用posix线程但也可以使用std的代码。定义两者时,应重新排列顺序以首先使用std。来自static_mutex.hpp第27

行的代码示例

1
2
3
4
#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"

第二,仍然有两个文件需要posix:signal_blocker.hpp和tss_ptr.hpp。由于仅支持Windows和POSIX,make将失败

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

更新

tss_ptr.hpp指出,如果定义了ASIO_HAS_THREAD_KEYWORD_EXTENSION,则不需要pthread。在用符号定义此符号后,make错误下降了一半,表明只有signal_blocker.hpp是此依赖项的来源。

影响signal_set_service.ipp

1
2
3
4
5
6
7
8
9
10
11
12
13
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;

和select_reactor.ipp

1
2
3
4
5
6
7
{
#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)
}