C ++ - Boost Thread / Bind / Shared_ptr: ошибка подтверждения - PullRequest
0 голосов
/ 07 октября 2011

У меня небольшая проблема, которую я не могу решить. Я делаю небольшой сервер, чтобы перенаправить на него свои сообщения системного журнала. Это очень просто, но я хотел бы знать, что я сделал неправильно, потому что при вызове 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: Если есть какие-то улучшения, чтобы быть более "потоко-безопасными", скажите мне, потому что это действительно меня интересует:)

Edit:

Спасибо за ваши комментарии, я думаю, что shared_ptr там действительно бесполезен, но мне может быть полезно наследовать класс от boost::enable_shared_from_this, чтобы гарантировать, что класс не будет освобожден до конца потока, что не должно происходить.

Start(), конечно, вызывается до 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() не работает по другой причине.

Спасибо за полезные советы

1 Ответ

1 голос
/ 07 октября 2011

Причина утверждения не сразу ясна из кода, который вы здесь представили, но, тем не менее, этот код может быть значительно улучшен.

Вы, похоже, используете 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(), что является единственным очевидным объяснением ошибки исходного кода.

...