找回密码
 用户注册

QQ登录

只需一步,快速开始

查看: 4499|回复: 3

使用proactor的应用如何在退出时避免内存泄漏?

[复制链接]
发表于 2007-12-12 23:53:40 | 显示全部楼层 |阅读模式
我的应用使用proactor模式,当应用退出时,调用end_event_loop先结束proactor事件处理循环.
然而如果此时有一个未完成的write调用,则会导致内存泄漏.(vc 2003下报告内存泄漏).
我的问题是:
1. 如果取消一个未完成的write调用?
2. 关闭proactor时,如何获取该未完成write调用持有的message block(从而释放其内存)?
谢谢!
 楼主| 发表于 2007-12-12 23:53:47 | 显示全部楼层
尝试调用异步处理对象的cancel()方法,不过未必成功。
我认为,不必关心异步发起产生的所谓“泄露”,无关紧要。因为系统已经停止运行,OS会自动回收。
再者,异步发起的请求,在得到处理的时候,就没有泄露了。
 楼主| 发表于 2007-12-12 23:53:55 | 显示全部楼层
>尝试调用异步处理对象的cancel()方法,不过未必成功。
是什么意思?调用ACE_Asynch_Read_Stream的cancel方法吗?不过未必成功是什么意思?

>不必关心异步发起产生的所谓“泄露”,无关紧要。因为系统已经停止运行,OS会自动回收。

是这样。我是想得到一个完美的解决方案。最好是能够解决该问题。
 楼主| 发表于 2007-12-12 23:54:44 | 显示全部楼层
这是我曾经的一段代码的简化版,应该能很好的解决你的问题:
  1. class MY_Handler : public ACE_Service_Handler
  2. {
  3. public:
  4.   MY_Handler(void)
  5.     : mblk_ (0)
  6.   {}
  7.   virtual ~DH_Handler(void)
  8.   { this->destroy (); }
  9.   // Called by ACE_Asynch_Acceptor when a client connects.
  10.   virtual void open (ACE_HANDLE new_handle,
  11.                      ACE_Message_Block &message_block)
  12.   {
  13.    reader_.open (*this, new_handle, 0, proactor ());
  14.    writer_.open (*this, new_handle, 0, proactor ());
  15.    
  16.    ACE_NEW_NORETURN (mblk_,
  17.                      ACE_Message_Block (ACE_DEFAULT_CDR_BUFSIZE));
  18.    // Align the Message Block for a CDR stream
  19.    ACE_CDR::mb_align (mblk_);
  20.    reader_.read (*mblk_, 自定义长度);
  21.   }
  22. protected:
  23.   // Handle input from clients.
  24.   virtual void handle_read_stream (const ACE_Asynch_Read_Stream::Result &result)
  25.   {
  26.    if (!result.success () || result.bytes_transferred () == 0)
  27.      delete this;
  28.    else if (result.bytes_transferred () < result.bytes_to_read ())
  29.      reader_.read (*mblk_,
  30.                    result.bytes_to_read () - result.bytes_transferred ());
  31.    else
  32.      writer_.write (*mblk_,
  33.                    mblk_.size ());
  34.   }
  35.   // Handle output to clients.
  36.   virtual void  handle_write_stream (const ACE_Asynch_Write_Stream::Result &result)
  37.   {
  38.    if (!result.success () || result.bytes_transferred () == 0)
  39.      delete this;
  40.    else
  41.    {
  42.     mblk_.reset ();
  43.     // Align the Message Block for a CDR stream
  44.     ACE_CDR::mb_align (mblk_);
  45.     reader_.read (*mblk_, 自定义长度);
  46.    }
  47.   }
  48.   // Called by destructor to release all resources. Can be override by sub class.
  49.   virtual void destroy (void)
  50.   {
  51.    reader_.cancel ();
  52.    writer_.cancel ();
  53.    ACE_OS::closesocket (handle ());
  54.    if (mblk_ != 0)
  55.      mblk_->release ();
  56.    mblk_ = 0;
  57.   }
  58. protected:
  59.   ACE_Message_Block *mblk_;       // Block to received
  60.   ACE_Asynch_Read_Stream reader_; // Async read factory
  61.   ACE_Asynch_Write_Stream writer_; // Async write factory
  62. };
复制代码
这个例子简单的从客户端读取一段数据流然后原封不动的返回给客户端,在对端关闭连接或handler的创建者手动关闭连接的时候,都只需要简单的删除维护该连接的handler就可以,handler自动清理socket句柄和ACE_Message_Block数据块,并cancel异步读写单元。

最后,在主线程结束的时候,你只需要在发起proactor的end_event_loop请求的同时,枚举并删除每个handler对象,然后调用ACE_Thread_Manager的wait等待正在进行中的异步动作的结束,就可以完全安全并无泄漏的终止你的应用。
您需要登录后才可以回帖 登录 | 用户注册

本版积分规则

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

GMT+8, 2024-11-23 18:42 , Processed in 0.013420 second(s), 5 queries , Redis On.

Powered by Discuz! X3.5

© 2001-2023 Discuz! Team.

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