web-dev-qa-db-ja.com

ASIOとstd :: threadを使用してC ++ 11アプリケーションを作成するときの「pthread_create」エラーへの未定義の参照

私はEclipse(実際にはザイリンクスSDKですが、Eclipseに基づいています)とg ++ 4.9.2を設定して、スタンドアロンASIOを使用するプロジェクトをコンパイルし、プロパティ-> C/C++ビルド->で-std = c ++ 11を使用しました設定->ツール設定->その他のフラグ。すべてのC++ 11機能を使用してコンパイルできます。

また、C/C++ General SymbolsでASIO_HAS_STD_THREAD, ASIO_STANDALONEなどを設定し、ASIOヘッダーがpthreadではなくstd::threadを使用することを期待しています。ただし、makeからのエラーが引き続き表示されます。

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を指定していないため、posix_thread.ippは(posix_thread.hppを介して)含めないでください。 ASIOの.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

容疑者1 -pthread

ほとんどの人が信じているのとは反対に、C++ 11は-pthreadを必要とせず、Eclipseで-pthreadなしの単純なプロジェクトをコンパイルしようとしました。しかし、私が間違っていれば私を訂正することができます。リンカオプションに-pthreadを入れるとコンパイルできますが、必要がない場合はpthreadを使用したくないと感じました。

容疑者2-ASIO makefile

Posix_tss_ptr.hppを検索すると、Makefile.amにも見つかりました。これがエラーに影響するかどうか?

では、問題の原因は何ですか?上記の2つの容疑者でない場合は?私の推論が正しい場合はpthreadを使用せずに、ソリューションがまだ純粋なC++ 11の方法を使用できることを願っています.

更新

ASIO_HAS_PTHREADSは私が定義したのではなく、ASIOがどこかでPOSIXスレッドを使用し、リンカーがオプション-pthreadを必要とするのはそのためです。次に、#errorディレクティブを使用してasio/detail/signal_blocker.hppまでトレースしました。定義されている場所は2つだけで、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は、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

そして、_PTHREADSは、gnuクロスコンパイラ(arm-xilinx-linux-gnueabi)のインクルードファイル(features.h、posix_opt.hなど)から定義されています。マクロを実際に定義したのは追跡しませんが、ASIOはマクロです。 _POSIX_THREADSを使用するソース。したがって、リンカーオプション-pthreadが存在する必要があります。

繰り返しになりますが、非ASIO C++ 11スレッドではg ++ 4.9.2の-pthreadは必要ありませんが、スタンドアロンASIOでは必要です。次のコードは、g ++ 4.9.2(EclipseベースのザイリンクスSDK)で-pthreadなしで正しくビルドされています。

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

プログラムがC++ 11で記述されているという事実は、pthreadライブラリとリンクする必要があるかどうかには関係ありません。 Posixスレッドが必要な場合は、そのライブラリをリンクする必要があります。

C++ 11はstd::threadクラスを提供し、準拠する各コンパイラの標準ライブラリは、ターゲットシステムがホストするいくつかのネイティブスレッドAPIを使用して、そのクラスの機能を実装する必要があります。 GCCはpthreadsを使用してそれを実装するため、std::threadとリンクしない限り、GCCで-pthreadオブジェクトを作成するプログラムを構築することはできません。この事実はasioとは関係ありません。

[〜#〜]後で[〜#〜]

私は実際に-std = c ++ 11だけを使用してstd :: stdを使用してpthreadなしでプログラムをビルドしました

GCCの一部のWindowsポートがデフォルトでlibpthreadにリンクしているという事実に誤解され、混乱していると思います。例えば。サンプルプログラムがthread.cppにある場合、TDM-GCC 4.9.2を使用してWindowsで正常にビルドできます。

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

しかし、冗長モードでビルドした場合:

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

非常に多くのライブラリオプションが舞台裏でリンカーに渡されていることがわかります。特に-lpthread

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

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
15
Mike Kinghan

コードの実行中は、g ++ ssss(コード名)を使用します。cpp-std = c ++ 11 -pthread

それが動作します

4
Ramanand Yadav

1. std :: threadは-pthreadを必要としません

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;
}

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. ASIOの-pthreadへの依存関係のソース

まず、スタンドアロン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"

次に、posixを必要とするファイルが2つあります:signal_blocker.hppとtss_ptr.hppです。 WindowsとPOSIXのみがサポートされているため、makeは失敗します

2つのファイルを完全に書き直してc ++ 11を使用することが可能かどうかはわかりませんが、これらの2つのファイルは、std :: threadではなく、-lpthreadへの依存関係のソースです。

更新

tss_ptr.hppは、ASIO_HAS_THREAD_KEYWORD_EXTENSIONが定義されているため、pthreadは必要ありません。これをシンボルで定義すると、makeエラーは半分になり、signal_blocker.hppはこの依存関係のソースです。

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;

そして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)
}
2
Splash