程序在一个月的运行中不断吃内存,一个月吃掉了32G的内存,但是线上系统还不能停,不能改配置。。。。 有什么好办法排除内存泄露的问题么?
1 linxy 2015-07-29 20:01:45 +08:00 换go |
![]() | 2 matthewgao OP @linxy 不现实。。。 |
![]() | 3 acros 2015-07-29 20:11:43 +08:00 占个座位等解答。 这种环境下,是不是只能靠内存dump分析了? |
![]() | 4 fo2w 2015-07-29 20:15:32 +08:00 看描述我完全不知道你是要解决问题还是排查问题 不停机不能改配置要解决问题那无解, 或者我太废柴暂时没想到办法 要查问题这种情况下钩子就好了 但是...我还是建议好好review一遍代码... 这种泄漏量肉眼我真不信看不出来 |
![]() | 5 sinxccc 2015-07-29 20:16:13 +08:00 我们常用的做法是首先复制一个尽可能跟在线系统一样的环境,然后如果性能说得过去的话用 valgrind 跑可疑进程,对性能要求高的话,加上自己包装过的 new/delete/malloc/free 然后跑一段时间看输出的统计。 分离出最可疑的地方之后再按照这个特征走查代码。 |
![]() | 6 lijianying10 2015-07-29 20:20:45 +08:00 ![]() 不知道是何种业务, 1. 取一份程序拷贝准备复现问题 2. 两个方面来确定问题的来源 1. 用更高的业务访问频率(业务参数)来模拟在线程序的情况,让问题显现更清楚 2. 满足上面一条之后,(如果是巨大循环的算法)每次注释掉一个模块,来排查问题。找到是那个大模块之后,再从大模块入手使用同样方法,直到找到泄露点。 1. 尽量避免注释掉依赖模块。从底层开始。 2. 模块的划分粒度大小很重要,影响排查速度 3. 如果是由独立业务堆砌出来的大型程序,要从业务划分来找到一个或者多个业务发生泄露,然后使用上面的方法 4. 如果十分确定使用上面两条找不到。最后一招CodeReview。 5. 找到来源之后修复一下,做项目回归测试。 希望此流程能帮到楼主。这也是我在做计算程序的时候排查泄露时候的方法。 |
7 ch3n2k 2015-07-29 20:32:34 +08:00 加大swap,让它泄漏去。话说什么程序不能停机啊?要改架构啊 |
![]() | 8 typcn 2015-07-29 20:42:31 +08:00 |
9 zhouc 2015-07-29 22:03:47 +08:00 你们的程序是server程序,不能load balance traffic? |
![]() | 10 jedihy 2015-07-29 22:16:44 +08:00 via iPhone 对,valgrind,差不多就这些办法。一般单元测试的时候就要按模块找出内存泄露,不然耦合到一起很难找了。 |
11 lsmgeb89 2015-07-29 22:25:29 +08:00 大型的 C/C++ 程序,一开始开始就要考虑到内存管理模块啊,团队要制定好内存使用的规则,这样出现内存泄漏就可以定位到那个 instance 和代码位置。 PS:用 Valgrind 跑很慢的,而且不一定能够定位的。 |
12 xylophone21 2015-07-29 22:38:08 +08:00 ![]() #define new(x) mynew(__FILE__,__LINE__,x); |
![]() | 13 signifox 2015-07-29 23:32:04 +08:00 gcc4.8以上版本用[AddressSanitizer]{https://code.google.com/p/address-sanitizer/wiki/AddressSanitizer}, 低版本的用[efence]{https://directory.fsf.org/wiki/Electric_Fence} 检查C++内存泄露的神器。 |
14 alphonsez 2015-07-30 00:07:20 +08:00 建议改成能重启的。老不能重启总是个麻烦,总不见得永远不部署吧?如果能重启就好办了,每天重启一次呗。 |
![]() | 15 akira 2015-07-30 00:59:37 +08:00 如果有完善的日志的话,可以试试从日志里分析出业务量变化和内存增加变化的关系。定位到业务的话 就比较好做代码review了 |
![]() | 16 dndx 2015-07-30 01:07:21 +08:00 via iPhone 用智能指针。 |
![]() | 17 JamesRuan 2015-07-30 02:01:11 +08:00 上Erlang/OTP |
![]() | 18 vietor 2015-07-30 08:16:50 +08:00 via Android 所有内存分配回收代码都过一遍, 尤其用指针封装的地方(智能指针,共享指针),许多人没理解就乱用,用错。我之前就将所有智能指针转成自写封装类,解决内存泄漏 |
19 nightv2 2015-07-30 09:43:08 +08:00 重启啊,至少能改善问题,然后排查是那个模块 |
![]() | 20 qyz0123321 2015-07-30 09:50:33 +08:00 智能指针是王道 |
![]() | 21 eliteYang 2015-07-30 10:13:16 +08:00 强烈推荐intel vtunes分析,或者全局用智能指针,或者全局排查指针申请和释放的地方,看看有没有因为什么情况导致申请完后一些条件不满足,没有走到释放 |
22 hitmanx 2015-07-30 10:30:42 +08:00 生产环境不能停机的话,可以开发环境重新跑一次,并打开valgrind\address sanitizer之类的工具在运行时检测一下内存泄露。如果这也不行的话,可以上一些静态代码分析工具看看,比如coverity之类的 |
![]() | 23 acgeo 2015-07-30 11:25:18 +08:00 楼上各位说得都是扯犊子的~~ 这种情况,吃内存是无法避免的~ 写个shell脚本 定时执行~ 这样每次执行完毕,进程结束会自动释放掉内存. |
24 pp3182429 2015-07-30 13:29:40 +08:00 以前每次都是check所有分配内存的地方,是不是释放了…找所有的new和malloc==#。。 |
![]() | 25 acgeo 2015-07-30 15:54:28 +08:00 楼上各位说得都是扯犊子的~~ 这种情况,吃内存是无法避免的~ 写个shell脚本 定时执行~ 这样每次执行完毕,进程结束会自动释放掉内存. |
![]() | 26 linux40 2015-07-30 16:27:50 +08:00 为什么不用标准库里的模板?虽然我不是很懂工程这种东西。。。 |
![]() | 27 magicyu1986 2015-07-30 17:07:28 +08:00 上测试环境一块一块的排查,真没有其他好办法。 最好还是上一套半自动内存管理的东西:智能指针,循环引用检查啥的。 |
![]() | 28 acgeo 2015-07-30 19:37:33 +08:00 楼上各位说得都是扯犊子的~~ 这种情况,吃内存是无法避免的~ 写个shell脚本 定时执行~ 这样每次执行完毕,进程结束会自动释放掉内存.! |
![]() | 29 matthewgao OP 程序比较老,写的时候没有一个好用的智能指针,然后是一个大牛自己写的智能指针,诡异的就在于各个版本从来没出过问题,就这一台机器,同版本的其他机器也没出过问题,这个机器也没什么特别特殊的配置,所以很诡异 我现在怀疑是STL,有些容器不会自动shrink的问题。 |
![]() | 30 matthewgao OP 总之还是谢谢各位,我去试试AddressSanitizer,看看有什么效果不 |
![]() | 31 matthewgao OP 我来做个了结,最终还是靠 review 代码, 找到了泄露的地方, 10w 行。。。 |