一个不起眼的手误,让我调了半小时

13 篇文章 1 订阅

一个不起眼的手误,让我调了半小时,大家最好先别看解析部分,自己练一下眼里吧。

运行是报段错误:

(3077573488) starting up
(3077573488) is exiting
段错误

下面给出错误代码:

  1 #include <ace/Task.h>
  2 #include <ace/Log_Msg.h>
  3 #include <ace/Thread_Manager.h>
  4 
  5 class ExitHandler : public ACE_At_Thread_Exit {
  6     public:
  7         virtual void apply (void) {
  8             ACE_DEBUG ((LM_DEBUG,
  9                         ACE_TEXT ("(%t) is exiting\n")));
 10             // Shutdown all devices.
 11         }
 12 };
 13 
 14 class MyThread : public ACE_Task_Base {
 15     public:
 16         MyThread (ExitHandler &eh) : eh_(eh) {}
 17         virtual int svc () {
 18             ACE_DEBUG ((LM_DEBUG,
 19                         ACE_TEXT ("(%t) starting up\n")));
 20 
 21             this->thr_mgr ()->at_exit (eh_);
 22 
 23             // Do something.
 24             ACE_OS::sleep (1);
 25 
 26             // Forcefully exit ();
 27             ACE_Thread::exit ();
 28 
 29             // Not reached.
 30             return 0;
 31         }
 32     private:
 33         ExitHandler eh_;
 34 };
 35 
 36 
 37 int ACE_TMAIN (int argc, ACE_TCHAR *argv[]) {
 38     ExitHandler eh;
 39 
 40     MyThread thread (eh);
 41     thread.activate ();
 42 
 43     ACE_Thread_Manager::instance ()->wait ();
 44     return 0;
 45 }




解析:

第33行应该声明为引用,即

 33         ExitHandler &eh_;

出现段错误的原因:

原因在于ACE_At_Thread_Exit的构造函数和析构函数

默认够在函数:

ACE_At_Thread_Exit::ACE_At_Thread_Exit (void)
  : next_ (0),
    td_ (0),
    was_applied_ (false),
    is_owner_ (true)
{
}

析构函数:

ACE_At_Thread_Exit::~ACE_At_Thread_Exit (void)
{
  this->do_apply ();
}

ACE_At_Thread_Exit::do_apply()函数的定义:

void ACE_At_Thread_Exit::do_apply (void)
{
  if (!this->was_applied_ && this->is_owner_)
    td_->at_pop();
}

可以看到,在默认构造函数中,was_applied_初始化为false,is_owner_初始化为true,而td_初始化为空指针。如果我们使用默认构造函数实例化了一个ACE_At_Thread_Exit类(或其子类)的实例,如果此实例没有被使用,则在实例销毁时将调用td_->at_pop()函数,由于td_为空指针,此行调用将会报段错误。

如果ACE_At_Thread_Exit类的实例被应用到某个ACE_Thread_Manager,则线程退出时将会设置was_applied_为false,这样析构函数中将不再调用td->at_pop()函数。

结论:这应该是ACE的一个bug吧,一个不能随便实例化的类,太危险了,使用时需格外小心。







评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值