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

来源:互联网 发布:程序员逆袭之路txt 编辑:程序博客网 时间:2024/04/20 11:36

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

运行是报段错误:

(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吧,一个不能随便实例化的类,太危险了,使用时需格外小心。