找回密码
 用户注册

QQ登录

只需一步,快速开始

查看: 4160|回复: 7

ACE Crashes on exit (see very very simple sample code included)

[复制链接]
发表于 2008-1-17 18:44:21 | 显示全部楼层 |阅读模式
ACE version :
This is ACE version 5.4, released Wed Jan 14 18:45:46 2004.

Visual C++ version 6 SP3.

--- SAMPLE BEGIN ---
  1. #include <ace/Event_Handler.h>
  2. #include <ace/reactor.h>
  3. #include <ace/OS_NS_sys_time.h>
  4. struct Main : public ACE_Event_Handler
  5. {
  6.          int _f;
  7.          int _t1;
  8.         Main() {_f = _t1 = 0;}
  9.          init();
  10.          virtual int handle_timeout(const ACE_Time_Value &tv, const void *arg);
  11. };
  12. Main::init()
  13. {
  14.          _t1 = ACE_Reactor::instance()->schedule_timer(this, (void *) 1, 0, 1);
  15. }
  16. int Main::handle_timeout(const ACE_Time_Value &tv, const void *arg)
  17. {
  18.          static int c = 0;
  19.          printf("t\n");
  20.          if (c++ == 3)
  21.                  _f = true;
  22.          return 0;
  23. }
  24. int main(int argc, char* argv[])
  25. {
  26.          Main m;
  27.         m.init();
  28.         while (!m._f)
  29.          {
  30.                  ACE_Reactor::instance()->handle_events();
  31.          }
  32.         return 0;
  33. }
复制代码

--- SAMPLE END ---
ACE crahses after exiting main().

If someone could help ...

Thank you for advance.
 楼主| 发表于 2008-1-17 18:44:32 | 显示全部楼层
Dr. Doug 是这样回答的:
The problem here is that you allocate Main m on the stack, so it is
destroyed by the time the Reactor's destructor tries to remove the
event handler.  Please see Chapters 3 and 4 of C++NPv2
<www.cs.wustl.edu/~schmidt/ACE/book2/> for information on how to avoid
this problem.

我的问题是:
Reactor在析构时会自动删除(delete)已登记的event handler吗?
如果是的话,如果避免以上问题?
如何让Reactor不自动删除已登记的event handler?

谢谢!
 楼主| 发表于 2008-1-17 18:44:45 | 显示全部楼层
追踪源代码,的确会逐个调用每个handle的handle_close(),
你可以自己删除啊,传递:DONT_CALL标志,不会调用handle_close.


ACE_Reactor::instance ()->remove_handler(impl->get_handle (), ACE_Event_Handler::DONT_CALL);
 楼主| 发表于 2008-1-17 18:44:53 | 显示全部楼层
导致crash的原因,其实不是堆上分配 OR 栈上分配。我已经做过程序验证,真正的原因是:
程序退出的时候,没有取消timer定时器,这样一来,造成栈错误。

       while (!m._f)
         {
                 ACE_Reactor::instance()->handle_events();
         }
//增加一行,不再出错。
       ACE_Reactor::instance()->cancel_timer(&m);
 楼主| 发表于 2008-1-17 18:45:02 | 显示全部楼层
我做实验验证,是这样的:
在程序退出时,由于m已经析构,但reactor此时又调用了m的handle_close,导致程序crash掉

如果上述m在堆上分配,程序就不会crash掉,但会导致内存泄漏
 楼主| 发表于 2008-1-17 18:45:08 | 显示全部楼层
一样有问题。内存堆在程序退出的时候,一样废除,只是代码还能访问而已。
handle_close默认的实现,只是简单的返回,不会造成这个错误。
你加上取消timer,就不会出错了。
 楼主| 发表于 2008-1-17 18:45:14 | 显示全部楼层
在windows平台下,ace中的reactor 在移除事件句柄时会有一个延时,即:如果你在栈上分配一个ACE_EventHandler对象,经常是当你退出了这个变量的作用阈,对象已经被析构后,事件句柄才从reactor内部的句柄列表中移除。这时如果调用对象的handle_close方法,就会导致异常退出.这种coredump行为是不可预期的,有时候根本不会出现。需要指出的是,有时候即使你在remove handler的时候传入了DONT_CALL标记,这个行为还是会发生。

   所以在windows平台下,event_handler的实例应该是new出来的,然后在handle_close方法使用delete this进行析构。以保证在调用handle_close方法的时候对象仍然存在。
在unix/linux平台下,则不存在这个问题。


上面的解释在C++NPv2 有,忘记在哪一页了,你可以翻翻。

置于这里的定时器没有释放,算是另外一个错误吧。
发表于 2009-8-30 19:12:24 | 显示全部楼层
re:: ACE_Reactor::instance ()->remove_handler(impl->get_handle (), ACE_Event_Handler::DONT_CALL);

如果crash at ACE_WFMO_Reactor_Handler_Repository::make_changes_in_current_infos (void) 。。。
。。。。L771 event_handler->handle_close (handle, masks);
跟踪,L680       while (i < this->max_handlep1_) 中 max_handlep1 不随remove_handler操作-1,
如果event_handler被手动释放,则非法指针

remove_handler和register_handler同时加上 DONT_CALL,则没有问题

ACE_Reactor::instance ()->register_handler(impl->get_handle (), ACE_Event_Handler::DONT_CALL);
。。。。。。
ACE_Reactor::instance ()->remove_handler(impl->get_handle (), ACE_Event_Handler::DONT_CALL);

[ 本帖最后由 xbbbbb 于 2009-8-30 19:16 编辑 ]
您需要登录后才可以回帖 登录 | 用户注册

本版积分规则

Archiver|手机版|小黑屋|ACE Developer ( 京ICP备06055248号 )

GMT+8, 2024-11-23 00:10 , Processed in 0.015518 second(s), 5 queries , Redis On.

Powered by Discuz! X3.5

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表