0

解決できない小さな問題があります。syslog メッセージをリダイレクトする小さなサーバーを作成しています。これは非常に基本的なことですが、呼び出し時に次のエラーが発生し続ける原因を知りたいと思いますjoin ()

/boost/path/shared_ptr.hpp:418: T* boost::shared_ptr< <template-parameter-1-1> >::operator->() const [with T = boost::thread]: Assertion `px != 0' failed.

コードはさらに説明します:

class SysLogServer
{
public:

  typedef boost::shared_ptr<boost::thread>  Ptr_thread;

  bool Start ()
  {
    ...
    _thrd = Ptr_thread(new boost::thread (boost::bind(&SysLogServer::run, this)));
    if (!_thrd.get ())
      return ERROR ("Thread couldn't be instanciated.");
    ...
  }

  bool Stop ()
  {
    ...
    _thrd->join ();
    ...
  }

private:

  void run()
  {
    ...
  }

  Ptr_thread _thrd;

};

ご助力ありがとうございます。

PS:より「スレッドセーフ」になるための改善点がある場合は、本当に興味があるので教えてください:)

編集:

shared_ptrコメントありがとうございます。実際には役に立たないと思いますboost::enable_shared_from_thisが、スレッドの終了前にクラスが解放されないようにするためにクラスを継承すると便利かもしれません。

Start()はもちろん before と呼ばれるStop()ので、属性で簡単なチェックを行いstateます。run()メソッドは単に接続を受け入れるだけです。

class SysLogServer
{
public:

  bool Start ()
  {
    ...
    _thrd = boost::thread(boost::bind(&SysLogServer::run, this)));
    ...
  }

  bool Stop ()
  {
    ...
    _thrd.join();
    ...
  }

  void run ()
  {
    std::cout << "Start running..." << std::endl; // never printed
    // Create a socket
    // Create a sockaddr_in
    // Bind them together
    while (!_serverStopped && !listen(sockfd, 5)) // on Stop(): _severStopped = true
     {
       // Get socket from accept
       // Print the received data
       // Close the socket given by accept
     }
    // close the first socket
  }

  boost::thread _thrd;
};

それは今動作します。以前はほとんど同じソリューションをポインターで使用しましたが、成功せず、友人のSIGSEGV :)

編集2:

Stop()サーバーが起動していることを確認するのを忘れていたため、ポインターでは機能しませんでした。メソッドは別のStart()理由で失敗します。

有益なアドバイスありがとうございます

4

1 に答える 1

1

このアサーションの理由は、ここに示したコードからはすぐにはわかりませんが、それでもなお、このコードは大幅に改善される可能性があります。

を使用してshared_ptrいるように見えますが、その必要はないようです。Ptr_threadに変更できますboost::thread。これにより、オブジェクトの有効期間を理解しやすい、より単純で効率的なコードが得られます。

コードは次のように変更できます。

class SysLogServer
{
public:

  bool Start ()
  {
      ...
      _thrd = boost::thread(boost::bind(&SysLogServer::run, this)));
      ...
  }

  bool Stop ()
  {
      ...
      _thrd.join();
      ...
  }

private:

    void run()
    {
        ...
    }

    boost::thread _thrd;

};

Stop()が呼び出される前に が呼び出された場合、このコードは依然として正しくありStart()ません。これは、元のコードが失敗した唯一の明白な説明です。

于 2011-10-07T10:18:27.040 に答える