找回密码
 用户注册

QQ登录

只需一步,快速开始

查看: 9127|回复: 15

关于Proactor使用Handler池内存泄露的问题

  [复制链接]
发表于 2010-7-21 11:30:10 | 显示全部楼层 |阅读模式
最近在做一些代码的分析,遇到一个奇怪的问题。
我写了一个简单的Proactor的例子,重载了ACE_Asynch_Acceptor,并创建了一个Handler对象池,在make_handler中获得一个Handler对象,当链接断开的时候归还make_handler到池中。
但是测试发现,在多线程并行测试下,内存不断的在增长,一开始我以为MessageBlock出现的问题,后来详细测试似乎MessageBlock没有问题。随着程序的运行,内存一直在增加。很奇怪,后来我把并行客户端链接线程减少到1,依然出现这样的情况。
调试了很久,似乎依然没有什么头绪。不知道内存增量到底是哪里产生的,Proactor服务器代码很简单,基本上能删的都删了。
呵呵,希望伙伴们帮我看看,给我一些建议。
代码以附件形式贴出,包括服务器和测试客户端。
我依然怀疑内存泄露点可能存在于ACE_Message_Block的部分。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?用户注册

×
发表于 2010-7-21 13:00:39 | 显示全部楼层
内存泄露问题用工具查一下吧。比分析代码快多了。
windows我一般用vld比较简单。
linux用valgrind也不错。
 楼主| 发表于 2010-7-21 13:44:10 | 显示全部楼层
我没有找到vid的工具,我一直用BoundsCheck。检测出的一些泄露都是单件的问题。
发表于 2010-7-21 15:00:08 | 显示全部楼层
本帖最后由 dwh0403 于 2010-7-21 15:21 编辑

PurenessProactor.cpp中的 typedef map<void*, _MemoryData*> mapMemory;  _MemoryData好像没有定义代码中也没有使用直接屏蔽掉就可以了。

经过我的测试win7+ace5.8.0 没有发现内存明显增长的情况。 倒是两个程序一跑CPU直接100%了
 楼主| 发表于 2010-7-21 15:33:18 | 显示全部楼层
我在win7+ACE5.7.4上有较大内存增长。测试程序内存也有增加。
发表于 2010-7-21 15:37:00 | 显示全部楼层
本帖最后由 modern 于 2010-7-21 15:39 编辑

VLD用起来超级简单。直接添加头文件,编个DEBUG版本看output就OK了。

obejct_manager相关那几坨内存泄露,基本都是一次的,
ACE的设计者认为这不是问题,而且改起来是一个超级大的工程,因此不会解决的。
BoundChecker是好东西,
不过貌似没有继续做下去了
我一直没有找到适合VS2008以上的版本。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?用户注册

×
发表于 2010-7-21 18:24:01 | 显示全部楼层
这几天事情太多,还没来及看工程.boundschecker有新版本,但不叫这个名字了.devpartner - 没有能适应最新VS.Studio的版本.
 楼主| 发表于 2010-7-22 18:15:05 | 显示全部楼层
本帖最后由 freeeyes 于 2010-7-22 18:35 编辑

感谢modern的工具,我正在测试。。
 楼主| 发表于 2010-7-26 10:37:02 | 显示全部楼层
这个问题我大概找到原因了。
如果我在Handler类里面使用
ACE_Asynch_Read_Stream*    m_preader;
ACE_Asynch_Write_Stream*   m_pwriter;
每次使用的时候创建(new)。每次链接断开的时候删除(delete)。这时候内存曲就是平的,如果我使用
ACE_Asynch_Read_Stream    m_reader;
ACE_Asynch_Write_Stream   m_writer;
这个时候,当我在链接关闭的时候cancel,就会有内存泄露。原因是里面的缓冲内存块似乎没有得到释放。
因为我使用的是Handler池的方法,反复利用handler从而提高效率,减少new和delete,所以在这里存在了一个问题。
呵呵,这部分谁研究过?
发表于 2010-7-26 11:58:04 | 显示全部楼层
我检查了一下系统的运行流程,认为找到了原因:
  1. int
  2. ACE_Asynch_Read_Stream::open (ACE_Handler &handler,
  3.                               ACE_HANDLE handle,
  4.                               const void *completion_key,
  5.                               ACE_Proactor *proactor)
  6. {
  7.   // Get a proactor for/from the user.
  8.   proactor = this->get_proactor (proactor, handler);
  9.   // Now let us get the implementation initialized.
  10.   if ((this->implementation_ = proactor->create_asynch_read_stream ()) == 0)
  11.     return -1;
复制代码
//这里,每次都会创建一个新的异步处理器
  1. ACE_Asynch_Read_Stream_Impl *
  2. ACE_WIN32_Proactor::create_asynch_read_stream (void)
  3. {
  4.   ACE_Asynch_Read_Stream_Impl *implementation = 0;
  5.   ACE_NEW_RETURN (implementation,
  6.                   ACE_WIN32_Asynch_Read_Stream (this),
  7.                   0);
  8.   return implementation;
  9. }
复制代码
freeeyes的工程,为了加快速度,把handler转变成了对象池,但ACE的代码显然没考虑过这样的应用。所以每次在handler对象open的时候,无论是否已经存在异步处理器,都会创建一个新的异步处理器,这导致了内存泄漏。而把m_reader/m_writer变成指针后,则会在delete的时候,自动的清除对应的异步处理器,就没有问题了。

改进方法嘛,修改ACE,做一下存在的判断。或者放弃这个模式。
您需要登录后才可以回帖 登录 | 用户注册

本版积分规则

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

GMT+8, 2024-11-22 07:48 , Processed in 0.024463 second(s), 6 queries , Redis On.

Powered by Discuz! X3.5

© 2001-2023 Discuz! Team.

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