简体   繁体   English

boost :: thread断言的share_ptr失败

[英]share_ptr of boost::thread assertion fail

class WIFITest
{
public:

  void StartTest();

  void Notify_Test(boost::shared_ptr<basic_msg> basic_msg, ID id );


private:
  void OpenStaMode_test();

private: 
  boost::shared_ptr<boost::thread> OpenStaMode_testThread;

  boost::shared_ptr<basic_msg> VMF_WIFI_NOTIFY_CLIENT_OPEN_MSG;  

  typedef boost::shared_ptr<boost::thread> THREAD;
  typedef boost::shared_ptr<basic_msg> MSG;
  std::map<ID,std::pair<THREAD,MSG>> map;
};  

void WIFITest::StartTest()
{ 
  map[ID::WIFI_REQ_CLIENT_OPEN] = std::make_pair(OpenStaMode_testThread,VMF_WIFI_NOTIFY_CLIENT_OPEN_MSG);

  this->OpenStaMode_testThread.reset(new boost::thread(&WIFITest::OpenStaMode_test,this));
  this->OpenStaMode_testThread->join();

}
void WIFITest::OpenStaMode_test()
{
  unsigned char strData[WIFI_SEND_BUF_SIZE_MIN];
  sendOpenReq(strData);
  try { 
    boost::this_thread::sleep(boost::posix_time::seconds(8));
  }
  catch(const boost::thread_interrupted&) {   

        std::cout<<"OpenStaMode_test success@ \n";

      }
    else {
        goto OpenStaMode_test_fail;
      }

    return;

  }
OpenStaMode_test_fail:
  printf("@WIFITest::OpenStaMode_test FAIL@@@@@@@@@@@@@@ \n");

}

void WIFITest::Notify_Test(boost::shared_ptr<basic_msg> basic_msg, ID id)
{
  map[id].second = basic_msg;

   map[id].first->interrupt();
  printf("@WIFITest::INTERRUPTED @@@@@@@@@@@@@@ \n");

}

First main will create StartTest instance and call StartTest(), When other code call Notify_Test, "map[id].first->interrupt();" First main将创建StartTest实例并调用StartTest(),当其他代码调用Notify_Test时,“ map [id] .first-> interrupt();” this sentence will produce following assertion fail, and crash the program. 这句话将产生以下断言失败,并使程序崩溃。

TestWIFI: ../../boost_1_55_0/boost/smart_ptr/shared_ptr.hpp:653: typename boost::detail::sp_member_access::type boost::shared_ptr::operator->() const [with T = boost::thread, typename boost::detail::sp_member_access::type = boost::thread*]: Assertion `px != 0' failed. TestWIFI:../../boost_1_55_0/boost/smart_ptr/shared_ptr.hpp:653:typename boost :: detail :: sp_member_access :: type boost :: shared_ptr :: operator->()const [with T = boost :::线程,类型名boost :: detail :: sp_member_access :: type = boost :: thread *]:断言px!= 0失败。

This line: 这行:

map[ID::WIFI_REQ_CLIENT_OPEN] = std::make_pair(OpenStaMode_testThread,VMF_WIFI_NOTIFY_CLIENT_OPEN_MSG);

stores into the map a copy of OpenStaMode_testThread , which, at this point, is empty. OpenStaMode_testThread的副本存储到地图中,此时该副本为空。

Then you call reset(new boost::thread(&WIFITestSuite::OpenStaMode_test,this)) on OpenStaMode_testThread , but that doesn't affect the copy already stored into the map. 然后,您在OpenStaMode_testThread上调用reset(new boost::thread(&WIFITestSuite::OpenStaMode_test,this)) ,但这不会影响已经存储在地图中的副本。

As a result, when you call map[id].first->interrupt(); 结果,当您调用map[id].first->interrupt(); , you are calling it on an empty shared_ptr , causing the assertion to fail. ,您在一个空的shared_ptr上调用它,导致断言失败。


As discussed below, there is a race condition here if a call to Notify_Test can occur after the thread has started execution but before the reset() call on the shared_ptr stores it into the map. 如下所述,如果在线程开始执行之后但在shared_ptr上的reset()调用将其存储到映射中之前,可以发生对Notify_Test的调用,则存在争用条件。 To fix this, use a mutex: 要解决此问题,请使用互斥锁:

class WIFITest
{
public:
  /* ... */
private:
  /* ... */

private: 
  boost::mutex mutex_;
  /* ... */
};  



void WIFITest::StartTest()
{ 
  {
    boost::lock_guard<boost::mutex> guard(mutex_);  // Takes ownership of the mutex
    map[ID::WIFI_REQ_CLIENT_OPEN] = std::make_pair(THREAD(), VMF_WIFI_NOTIFY_CLIENT_OPEN_MSG);
    map[ID::WIFI_REQ_CLIENT_OPEN].first.reset(new boost::thread(&WIFITest::OpenStaMode_test,this));
    // At this point the thread has started and the pointer has been stored into the map
  }  // guard is destructed and mutex released here 
     // so that we don't hold the mutex while waiting
     // for the thread to finish.

  map[ID::WIFI_REQ_CLIENT_OPEN].first->join();
}

/* ... */

void WIFITest::Notify_Test(boost::shared_ptr<basic_msg> basic_msg, ID id)
{
  boost::lock_guard<boost::mutex> guard(mutex_); // Takes ownership of the mutex
  map[id].second = basic_msg;
  map[id].first->interrupt();
  printf("@WIFITest::INTERRUPTED @@@@@@@@@@@@@@ \n");

}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM