1

C++11のスレッドライブラリを使用してマルチスレッドソフトウェアを作成しようとしています。インターネット上にあるいくつかの基本的なチュートリアルは、期待どおりにコンパイルして実行できます。しかし、クラスに分けられた私自身のアプリケーションは常に例外をスローします。

コードのどの部分を修正する必要があるか教えてもらえますか?

$ clang++ -std=c++11 -stdlib=libc++ BaseInterface.cxx -c -o BaseInterface.o
$ clang++ -std=c++11 -stdlib=libc++ SocketReceiver.cxx -c -o SocketReceiver.o
$ clang++ -std=c++11 -stdlib=libc++ main.cxx -c -o main.o
$ clang++ -std=c++11 -stdlib=libc++ main.o BaseInterface.o SocketReceiver.o -o main
$ gdb main  
(gdb) run
Starting program: /Users/oxon/test/main 
Reading symbols for shared libraries ++............................ done
libc++abi.dylib: terminate called throwing an exception

Program received signal SIGABRT, Aborted.
[Switching to process 859 thread 0x40b]
0x00007fff88df8212 in __pthread_kill ()
(gdb) bt
#0  0x00007fff88df8212 in __pthread_kill ()
#1  0x00007fff8bc85af4 in pthread_kill ()
#2  0x00007fff8bcc9dce in abort ()
#3  0x00007fff894d3a17 in abort_message ()
#4  0x00007fff894d13c6 in default_terminate ()
#5  0x00007fff89874887 in _objc_terminate ()
#6  0x00007fff894d13f5 in safe_handler_caller ()
#7  0x00007fff894d1450 in std::terminate ()
#8  0x00007fff894d25b7 in __cxa_throw ()
#9  0x00007fff8a9ba3b9 in std::__1::thread::join ()
#10 0x0000000100000cf0 in SocketReceiver::Receive ()
#11 0x0000000100000c6d in SocketReceiver::DoReceive ()
#12 0x0000000100001593 in _ZNSt3__114__thread_proxyINS_5tupleIJPFPvS2_ES2_EEEEES2_S2_ ()
#13 0x00007fff8bc84742 in _pthread_start ()
#14 0x00007fff8bc71181 in thread_start ()

これはOSX10.8での結果です。GCC4.4を搭載したScientificLinux6でも同様の結果が得られます。

= BaseInterface.h =

#ifndef BASE_INTERFACE_H
#define BASE_INTERFACE_H

#include "SocketReceiver.h"

class BaseInterface
{
private:
  SocketReceiver*    fReceiver;

public:
  BaseInterface();
  virtual ~BaseInterface();

  virtual void Close();
  virtual void Open();
;

#endif

= BaseInterface.cxx =

#include <iostream>

#include <string.h>
#include <unistd.h>

#include "BaseInterface.h"

BaseInterface::BaseInterface()
{
  fReceiver = new SocketReceiver(this);
}

//______________________________________________________________________________
BaseInterface::~BaseInterface()
{
  Close();
  delete fReceiver;
  fReceiver = 0;
}

//______________________________________________________________________________
void BaseInterface::Close()
{
  fReceiver->Stop();
  usleep(10000);

  while(fReceiver->IsRunning()){
    usleep(10000);
  } // while
}

//______________________________________________________________________________
void BaseInterface::Open()
{
  fReceiver->Start();

}

= SocketReceiver.h =

#ifndef SOCKET_RECEIVER_H
#define SOCKET_RECEIVER_H

#include <thread>
#include <mutex>

class BaseInterface;

class SocketReceiver
{
private:
  BaseInterface*             fInterface;
  bool                       fIsRunning;
  std::mutex                 fMutex;
  bool                       fStop;
  std::thread*               fThread;

public:
  SocketReceiver(BaseInterface* interface = 0);
  virtual ~SocketReceiver();

  bool             IsRunning() const {return fThread ? true : false;}
  static void*     DoReceive(void* arg);
  void             Receive();
  void             Start();
  void             Stop();
};

#endif

= SocketReceiver.cxx =

#include <iostream>
#include <thread>
#include <unistd.h>

#include "BaseInterface.h"
#include "SocketReceiver.h"

SocketReceiver::SocketReceiver(BaseInterface* interface)
{
  fInterface = interface;
  fStop = true;
  fThread = 0;
}

//______________________________________________________________________________
SocketReceiver::~SocketReceiver()
{
}

//______________________________________________________________________________
void* SocketReceiver::DoReceive(void* arg)
{
  SocketReceiver* receiver = (SocketReceiver*)arg;
  receiver->Receive();

  return 0;
}

//______________________________________________________________________________
void SocketReceiver::Receive()
{
  while(not fStop){
    fMutex.lock();
    usleep(10000);
    fMutex.unlock();
  } // while

  fThread->join();

  delete fThread;
  fThread = 0;
}

//______________________________________________________________________________
void SocketReceiver::Start()
{
  fStop = false;
  fThread  = new std::thread(DoReceive, (void*)this);
}

//______________________________________________________________________________
void SocketReceiver::Stop()
{
  fStop = true;
}

= main.cxx =

#include "BaseInterface.h"

int main()
{
  BaseInterface interface;
  interface.Open();
  interface.Close();

  return 0;
}
4

2 に答える 2

4

によって実行される関数がstd::thread終了し、例外が発生した場合は、 thenstd::terminateが呼び出されます。

std::thread::join()が同じスレッドで呼び出された場合std::system_error、エラー コードをスローするように指定されています。つまり、スレッドはそれ自体に参加できません。そのため、スレッドを結合しようとすると、例外が発生してプロセスが終了します。スレッドは自分自身に参加することはできません。参加は「スレッドが完了するのを待つ」と定義されているため、明らかにスレッド自体では実行できません。終了するまで待機することはできません。スレッドが終了するまで発生しません。これは、呼び出しが終了するまで発生しません...これがどこに向かっているのかわかりますか?resource_deadlock_would_occurjoin()join()join()

また、なぜこれを行うのですか?

fThread  = new std::thread(DoReceive, (void*)this);

std::threadではありませんpthread_create。渡す必要はありませんvoid*。単に取り除いDoReceiveて呼び出します。

fThread  = new std::thread(&SocketReceiver::Receive, this);

そして、なぜあなたはstd::thread割り当てられているのnewですか? これも必要ではありません。ポインターが null でないかどうかを確認する代わりに、std::threadメンバーを使用joinable()してアクティブかどうかを確認するために使用できます。

于 2013-03-07T09:24:49.347 に答える
4

あなたはスレッド自体に参加しています。joinのように、スレッドを呼び出しSocketReceiver::Stopます。

join呼び出されると、基になるデータがクリーンアップされます。実行中のスレッドでそれを呼び出すと、スレッドがまだデータを必要としている間、そのデータは削除されます。

于 2013-03-07T09:17:58.453 に答える