Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1090236
  • 博文数量: 143
  • 博客积分: 969
  • 博客等级: 准尉
  • 技术积分: 1765
  • 用 户 组: 普通用户
  • 注册时间: 2011-07-30 12:09
文章分类

全部博文(143)

文章存档

2023年(4)

2021年(2)

2020年(4)

2019年(4)

2018年(33)

2017年(6)

2016年(13)

2014年(7)

2013年(23)

2012年(33)

2011年(14)

我的朋友

分类: 云计算

2016-08-20 15:59:33

 

问题描述

       某服务前端机器(nginx主机)125G内存,每三天左右,主机内存可用内存为0,重启nginx进程,可用内存又恢复正常,这种现象表明nginx进程存在内存泄漏。

临时措施

   1、写定时脚本,每小时检查一次主机内存,小于5G时重启nginx进程

分析过程

1、  仔细认真分析阅读相关代码,考虑各种正常和异常情况,是否有程序退出时没有释放分配出来的内存

2、  借助其它工具进行检查内存泄漏点,这里使用的是valgrind ,具体使用如下

1)       valgrind --tool=memcheck --leak-check=full --show-reachable=yes /usr/local/nginx/sbin/nginx 启动进程

2)       进行正常的业务逻辑请求测试

3)       /usr/local/nginx/sbin/nginx  -s stop停止进程

4)       查看valgrind返回的结果

==8395== LEAK SUMMARY:

==8395==    definitely lost: 8,264 bytes in 2 blocks. //确实存在内存泄漏

==8395==    indirectly lost: 1,154,454 bytes in 229 blocks. //间接的存在内存泄漏

==8395==    possibly lost: 160 bytes in 1 blocks. //可能存在内存泄漏

==8395==    still reachable: 13,461,267 bytes in 3,059 blocks.

==8395==    suppressed: 0 bytes in 0 blocks.

 

5)       说明确实存在内存泄漏,进一步查看valgrind结果,发现内存泄漏点

 

==8395== 1,162,718 (8,264 direct, 1,154,454 indirect) bytes in 2 blocks are definitely lost in loss record 11 of 15

==8395==    at 0x40053C0: malloc (vg_replace_malloc.c:149)

==8395==    by 0x42EA6E3: AcquireMagickMemory (memory.c:464)

==8395==    by 0x4113FFA: CloneMagickWandFromImages (magick-image.c:97)

==8395==    by 0x80F7C53: dfs_image_resize (cfftn.c:1581)

6)       通过这些函数堆栈信息发现,使用第三方库ImageMagick进行图片压缩裁剪的时候存在内存泄漏,对比代码发现

magick_wand = MagickCoalesceImages(magick_wand); 比较可疑

7)       查看MagickCoalesceImages函数实现,发现这个函数内部最终会返回malloc的内存, MagickCoalesceImages malloc的值返回给magick_wand,而magick_wand原来指向的内存哪里去了?没有找到对应指针释放,这就是传说中内存泄漏。

解决方案

1、修改问题代码,返回值赋给新的变量,函数返回或结束时释放返回的内存指针

MagickWand  *magick_wand_new = MagickCoalesceImages(magick_wand);

…..

If(magick_wand_new!=NULL)

{

   DestroyMagickWand(magick_wand_new);

}

2、代码修改后用valgrind查看,没有发现内存泄漏

==8394== LEAK SUMMARY:

==8394==    definitely lost: 0 bytes in 0 blocks.

==8394==    possibly lost: 0 bytes in 0 blocks.

==8394==    still reachable: 34,030 bytes in 2,015 blocks.

==8394==    suppressed: 0 bytes in 0 blocks.

总结

1、  对于内存泄漏这种问题,要反复仔细的检查代码,考虑各种正常或异常情况下,返回时是否没有释放内存

2、  要善于借助工具来分析,排查问题

3、  在使用第三方库的时候,要仔细阅读接口的使用说明文档及返回值情况。最好能查看接口的实现

4、  在对外提供接口时,尽量做到谁分配内存,谁释放。不要在接口内分配内存,在接口外释放的这种情况。

 

 

 

阅读(1222) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~