找回密码
 用户注册

QQ登录

只需一步,快速开始

查看: 5444|回复: 4

Proactor模式下ACE_Asynch_Connector内存泄露问题

[复制链接]
发表于 2010-7-2 16:08:15 | 显示全部楼层 |阅读模式
void CProactorClient::Release()
{
    if (this->handle () != ACE_INVALID_HANDLE)
    {
        this->reader_.cancel();
        this->writer_.cancel();
        ACE_OS::shutdown(this->handle_, ACE_SHUTDOWN_BOTH);
        ACE_OS::closesocket (this->handle ());
        this->handle (ACE_INVALID_HANDLE);   
        delete this;
    }
    cur_ = NULL;
}

void CProactorClient::open (ACE_HANDLE h, ACE_Message_Block&)
{

     if (this->reader_.open (*this, h) != 0 )
     {
         ACE_ERROR ((LM_ERROR, ACE_TEXT ("%p\n"),
             ACE_TEXT ("CProactorClient open reader_")));
        
         delete this;
         return;
     }
      if (this->writer_.open (*this) != 0 )
      {
          delete this;
          ACE_ERROR ((LM_ERROR, ACE_TEXT ("%p\n"),
              ACE_TEXT ("CProactorClient open write_")));
          return;
      }
   
    msgblock_ = new ACE_Message_Block(1024*10);
     if (this->reader_.read (*msgblock_, msgblock_->space ()) != 0)
     {
        ACE_TRACE("Begin read fail\n");
         return;
     }
   
    ACE_TRACE("Begin open OK \n");
    TRACE("Begin client open OK \n");
}

void CProactorClient::handle_read_stream(const ACE_Asynch_Read_Stream::Result &result)
{
    ACE_Message_Block &mb = result.message_block ();
    if (!result.success () || result.bytes_transferred () == 0)
    {
        
        ACE_TRACE("Client Close. \r\n");   
        TRACE("Client Close. \r\n");   
        this->Release();
        return;
    }
   
    msgblock_->reset();
     if (this->reader_.read (*msgblock_, msgblock_->space ()) != 0)
    {
        ACE_TRACE("read data failed!");
        TRACE("read data failed!\r\n");
    }
}

void CProactorClient::handle_write_stream(const ACE_Asynch_Write_Stream::Result &result)
{
    ACE_Message_Block &mb = result.message_block ();
    mb.release();
}

int CProactorClient::WriteDate(char *szSendBuf, int nSendCnt)
{

    ACE_Message_Block *smb = new ACE_Message_Block(nSendCnt+1);
    smb->copy(szSendBuf, nSendCnt);
    int nResult = this->writer_.write(*smb, smb->length());
   
     return nResult;
}

Windows XP+VS2008,非常简单的客户端连接处理类,拷贝例子修改下的。

连接服务器时调用:

    ACE_Asynch_Connector<CProactorClient> m_curConnector;
    ACE_INET_Addr addr(m_nConnectPort, (char*)(LPCSTR)m_strSvrIPAddr);        
    m_curConnector.open();
    m_curConnector.connect(addr);

每次连接成功后,通过任务管理器可以发现内存增长了,但是连接断开后,内存没有减下来,
通过跟踪调试,发现connect()里面会new 不少东西,据说这些东西在完成回调后会释放的,
但是搞不懂在哪里释放。另外可以确认,连接断开的时候delete this被调用。


大虾们出来指点下,看看哪里写出了什么,或者是还需要调用什么来释放连接时产生的内存。

PS: 做过测试,只连接不做任何数据的收发操作,同样会存在内存增长,所以可以确认连接的时候
ACE里面new的内存在delete this之后还是没有被释放的。
发表于 2010-7-2 17:28:36 | 显示全部楼层
用工具查比较理想。
使用boundschecker或者purify.
发表于 2010-7-2 18:26:42 | 显示全部楼层
泄露似乎是你的Message_block没有释放。
  if (!result.success () || result.bytes_transferred () == 0)
    {
        
        ACE_TRACE("Client Close. \r\n");   
        TRACE("Client Close. \r\n");   
        this->Release();    <-这里你的mb没有release()
        return;
    }

多看看ACE的Test例子,有助于学习。
 楼主| 发表于 2010-7-3 10:37:32 | 显示全部楼层
接受数据只使用一个msgblock_,这个在析构函数中已经释放,不是该变量的问题。
发表于 2010-7-5 10:28:51 | 显示全部楼层
你把
    msgblock_ = new ACE_Message_Block(1024*10);
     if (this->reader_.read (*msgblock_, msgblock_->space ()) != 0)
     {
        ACE_TRACE("Begin read fail\n");
         return;
     }
注释掉,再看内存有无泄漏。若没有就可以基本肯定在handle_read_stream()函数里面的问题。
1.mb->release();未必会释放你的内存,这要看你的Message_block引用计数器的数值。
2.Proactor是异步模式,可能会并行调用你的handle_read_stream(),这里要注意你的内存指针。
您需要登录后才可以回帖 登录 | 用户注册

本版积分规则

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

GMT+8, 2024-12-23 04:03 , Processed in 0.013123 second(s), 6 queries , Redis On.

Powered by Discuz! X3.5

© 2001-2023 Discuz! Team.

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