免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
12下一页
最近访问板块 发新帖
查看: 5908 | 回复: 17
打印 上一主题 下一主题

Ubuntu下的多线程c++开发,遇到了一个内存释放的问题,求高人指点下 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2010-12-05 00:34 |只看该作者 |正序浏览
本帖最后由 licaduo 于 2010-12-05 00:45 编辑

我最近在Ubuntu下做了一个c++程序,遇到一个内存释放的问题,纠结了一周了,实在搞不清楚,请高人指点下小弟。
我这边开发的程序处理流程大概如下: 程序是多线程架构,主线程负责网络接收,收到网络包之后,new一块内存存放这个数据包,把指针放入接收队列,业务处理线程从接收队列读取数据包,处理完后new一片内存存放需要发送的数据包,把刚才的数据包指针放入发送队列,然后释放刚才读取的接收数据包的指针。发送线程从发送队列中读取数据包,发送出去,释放发送数据包指针的内存。
    现在的问题是:在并发压力不大的时候,从top的结果看,进程的内存占用很正常,在处理请求包的时候占用内存增长,数据包处理完之后,占用的内存回到一个比较低的水平。但是在突发的压力比较大的时候,进程的内存占用增长,但是在系统压力回落到比较小的水平的时候,内存占用不下降,这样慢慢的进程占用的内存不断上涨。现在差不多进程运行一天内存涨150m,基本上3,4天我重启一次进程。我用Valgrind检测过程序没有内存泄露。另外我放入队列的数据结构中用到了string。   
     我开始使用的队列使用标准库的 queue实现,后来改成list实现,但是这个问题似乎没有什么改进。
    这两天从网上搜索了相关的问题,我怀疑我遇到的问题是不是与glibc的内存释放机制有关系。 之前同样的线程模型,在suse上运行似乎没什么问题,不过之前在suse上运行的程序中放入队列的数据结构中没有用到string,都是基本的int和char数组。这个问题纠结了一周了,实在搞不清楚为什么,代码上似乎没有什么明显的问题。

论坛徽章:
0
18 [报告]
发表于 2010-12-06 17:22 |只看该作者
我今天又改了代码,观察了半天,内存占用基本控制下来了,多谢各位的指点。
现在的解决方式是在放入队列的 数据结构中又用了指针,相当于用两层的指针保存网络数据。
另外我也很怀疑string的内存释放问题。但是今天白天的程序表现还可以,再观察几天,看看是不是真的解决了问题。具体的原因再研究研究。
再次感谢各位的指点

论坛徽章:
0
17 [报告]
发表于 2010-12-06 13:56 |只看该作者
问题基本上可以确定是allocator的问题。SGI STL/STLort  的allocator不会自动释放内存,所以程序的内存占用 ...
hzhzorange 发表于 2010-12-06 07:54



    这位仁兄说的对,如果业务处理不过来,你接收新信息反而会导致系统性能下降,很快达到瓶颈,另外,楼上说用内存池不错,TCMalloc也很不错,它实际也是个内存池管理

论坛徽章:
0
16 [报告]
发表于 2010-12-06 10:52 |只看该作者
stl + c++ 服务器 运行5个月。内存无明显增长的飘过。
毫无压力。

动态的申请 或者删除 很大的string  会遇到 问题。 没找到解决方案,自己new delete 解决。

应该是你的代码本身有泄漏。

不要小看现在 OS 的内存管理能力。  多在自己的身上找问题。 你这种情况 可以说很明显的 泄漏了,
在类身上加 计数器。 日志打印计数器 很快就能看到问题。

论坛徽章:
0
15 [报告]
发表于 2010-12-06 07:54 |只看该作者
问题基本上可以确定是allocator的问题。SGI STL/STLort  的allocator不会自动释放内存,所以程序的内存占用取决于最高峰的时候所有容器占用多少内存。
你可以打开STL的源文件看看版权声明,以确定是什么版本的STL
另外你可以尝试使用  std::list<obj*,  std::allocator<obj*> >  memQueue,或者  std::list<obj*,  std::allocator > .

还有,你的设计存在问题,试想,如果 inQueue里面右面已经有  1000条记录,这就说明你的业务线程根本就处理不过来,而此时你允许往inQueue里面再添加数据,其实是没有意义的。正确的做法是限制 Queue的大小为N,如果已经到达了N,网络线程就阻塞。

论坛徽章:
1
申猴
日期:2014-02-11 14:50:31
14 [报告]
发表于 2010-12-06 00:09 |只看该作者
我不知道stl里面是什么实现的,但glibc malloc的实现,如果最顶端的内存在用,那么无论中间的内存在不在用都不能释放的

论坛徽章:
0
13 [报告]
发表于 2010-12-05 21:56 |只看该作者
會不會是stl容器的內存分配並沒有釋放的原因?  queue list刪除節點時候會不會立馬釋放內存呢?

这个确实是需要研究下,我自己放入stl容器的内存用完了是释放了的,但是stl本身的内存有没有释放确实没有控制,不知道怎么去控制这个。我好好研究下这个。
内存池,我也考虑下。

论坛徽章:
0
12 [报告]
发表于 2010-12-05 21:53 |只看该作者
楼上的建议我确实需要仔细考虑下,

论坛徽章:
1
双子座
日期:2014-08-29 17:15:03
11 [报告]
发表于 2010-12-05 20:40 |只看该作者
會不會是stl容器的內存分配並沒有釋放的原因?  queue list刪除節點時候會不會立馬釋放內存呢?

內存池的話可以用boost中的object pool 吧。

還有就是遇到大量數據包來臨的時候,是不是應該是做一下限制, 而不是一味講收到的數據接受進來? 抑或是應該增加處理的速度或者是增加處理的綫程數量?

论坛徽章:
0
10 [报告]
发表于 2010-12-05 19:50 |只看该作者
只能用内存池,你用了stl,还得实现allocator。。。
你可以试试别的malloc实现,比如TCMalloc
  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP