贝贝花花包包店,精品555皮具,钱夹,皮夹

字体:  

Proactor中调用delete this 框架报错?

peakzhang 发表于: 2008-7-15 22:50 来源: ACE 开发者

最近在用ACE Proactor框架写一个类似于Proxy的程序,在内网和外网之间转发数据包,但是发现当内网Socket断开以后,程序回调handle_read_stream函数中,此时我Delete外网对应的Handler(断掉外网的TCP连接)和内网的Handler,继续执行Proactor框架报错,具体情况如下:
     比如:
      在handle_read_stream中 delete internalHandler; delete externalHandler;后
   程序在 ACE_Proactor::instance()->proactor_run_event_loop();报错,好像是提示内存有误
由于小弟水平有限,不知这样的问题该如何解决,请教各位大虾了,不啻感激!

最新回复

peakzhang at 2008-7-15 22:50:33
这是因为你调用 delete 后,ACE_Proactor::instance()->proactor_run_event_loop();还在使用你的 handler 类中的消息块引起的,你必须保证在这些消息块都被回调完后,再被删除,

好好看一下ACE的例子,会有帮助的
peakzhang at 2008-7-15 22:50:43
我刚刚碰见一个这样的问题,解决方案就是,进行线程的同步。保证在delete前,相关的线程肯定退出了。就一定不会有问题
peakzhang at 2008-7-15 22:50:52
如何才能保证相关的线程肯定都退出了呢?我在Delete之前已经加了线程互斥,但问题依然存在, 在这个程序中我在一条连接的handle_read_stream中将收到的消息块直接调用另外一条链路Handler的异步Write方法,请问这样的设计是否合理(曾经考虑过把每条连接都对应一个Queue,Handler收到消息以后就把数据放到另外一个连接的队列中,把两个Handler之间的耦合通过队列隔开?)
peakzhang at 2008-7-15 22:51:04
对此 handler 类设置一个读写计数,当此计数器的值为0时再退出即可
peakzhang at 2008-7-15 22:51:12
就是经常使用的引用计数的技术。非常方便的。
peakzhang at 2008-7-15 22:51:19
初步设想在调用Handler的read和write提交异步操作之前使Handler的计数加一,在handle_read_stream和handle_write_stream中使计数减一,当在handle_read_stream中检测到连接断开以后首先调用shutdown和closesocket关闭本端的Socket连接,然后调用当前Handler的Cancel方法取消已经提交车操作,再判断当前Handler计数是否大于一(如果大于一表明还有线程对Handler作引用),如果等于0,则执行delete this并返回

请问大家这样的思路不知是否可行,另外如果当前Handler计数不为0,那么delete这个Handler的操作应该从哪处来完成呢?是否还需要启动另外一个监视线程定时判断Handler计数是否为0,若为0则从监视线程delete该Handler?
peakzhang at 2008-7-15 22:51:29
用监控线程?那不是成了垃圾收集了么,效率多差呀。
办法是很简单的,你学过COM没有,其实就是用COM的引用计数的技术,给对象设置一个AddRef和Release方法,只要调用了对象的方法,就AddRef,结束操作就Release,在Release里面,发现引用计数成为0,则delete this,肯定不会出错。
需要注意的要点:
1、引用计数是一个变量,初始值最好是1而不是0,你想想为什么。
2、操作引用计数,一定要增加多线程保护,而且Release里面,不可以使用ACE_GUARD宏。
peakzhang at 2008-7-15 22:51:40
在对象的方法中设置AddRef和Release机制恐怕够戗,因为调用Handler对象成员ACE_Asynch_Write_Stream的Write或ACE_Asynch_Read_Stream的read方法是异步的,调用立刻就会返回,那只是通知框架需要做一个对应的操作,是否需要对这个操作进行统计?
peakzhang at 2008-7-15 22:51:45
你理解错误,不是在异步读写的时候处理引用计数,而是在数据收取完毕后的处理中使用。
peakzhang at 2008-7-15 22:51:56
我的方法是此计数不为0时,就等个几十毫秒,把CPU给PROACTOR,让其尽快处理那些读写操作,然后再判断是否为0,此时再删除之,一般情况下等了这么长时间后,计数都会变为0,所以是比较安全的;若此时计数还大于0,那就是在其它地方出错了,再等多少时间也不会减少为0了,这种情况比较少见,运行几天也不一定能碰到一次;虽然这种方式不是很完美,但我觉得比添加了监视线程为好一点。。。
peakzhang at 2008-7-15 22:52:06
不是最佳方案 - 直接给处理器对象增加引用计数即可,方便直接。
peakzhang at 2008-7-15 22:52:14
这个对象是处理器对象,很简单的。C++网络编程卷2的例子中就有
peakzhang at 2008-7-15 22:52:23
在Handler handle_read_stream和handle_write_stream中加入引用计数机制后,问题得到初步解决,由此感觉在类似多线程程序中这样的问题要引起严重的重视:)

在此感谢winston和各位的大力帮助!