ACE Crashes on exit (see very very simple sample code included)
ACE version :This is ACE version 5.4, released Wed Jan 14 18:45:46 2004.
Visual C++ version 6 SP3.
--- SAMPLE BEGIN ---
#include <ace/Event_Handler.h>
#include <ace/reactor.h>
#include <ace/OS_NS_sys_time.h>
struct Main : public ACE_Event_Handler
{
int _f;
int _t1;
Main() {_f = _t1 = 0;}
init();
virtual int handle_timeout(const ACE_Time_Value &tv, const void *arg);
};
Main::init()
{
_t1 = ACE_Reactor::instance()->schedule_timer(this, (void *) 1, 0, 1);
}
int Main::handle_timeout(const ACE_Time_Value &tv, const void *arg)
{
static int c = 0;
printf("t\n");
if (c++ == 3)
_f = true;
return 0;
}
int main(int argc, char* argv[])
{
Main m;
m.init();
while (!m._f)
{
ACE_Reactor::instance()->handle_events();
}
return 0;
}
--- SAMPLE END ---
ACE crahses after exiting main().
If someone could help ...
Thank you for advance. 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?
谢谢! 追踪源代码,的确会逐个调用每个handle的handle_close(),
你可以自己删除啊,传递:DONT_CALL标志,不会调用handle_close.
ACE_Reactor::instance ()->remove_handler(impl->get_handle (), ACE_Event_Handler::DONT_CALL); 导致crash的原因,其实不是堆上分配 OR 栈上分配。我已经做过程序验证,真正的原因是:
程序退出的时候,没有取消timer定时器,这样一来,造成栈错误。
while (!m._f)
{
ACE_Reactor::instance()->handle_events();
}
//增加一行,不再出错。
ACE_Reactor::instance()->cancel_timer(&m); 我做实验验证,是这样的:
在程序退出时,由于m已经析构,但reactor此时又调用了m的handle_close,导致程序crash掉
如果上述m在堆上分配,程序就不会crash掉,但会导致内存泄漏 一样有问题。内存堆在程序退出的时候,一样废除,只是代码还能访问而已。
handle_close默认的实现,只是简单的返回,不会造成这个错误。
你加上取消timer,就不会出错了。 在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 有,忘记在哪一页了,你可以翻翻。
置于这里的定时器没有释放,算是另外一个错误吧。 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 编辑 ]
页:
[1]