linux动态分配内存经常会遇到俩个问题:
- 内存没有及时回收,发生内存泄露
- 访问的是已分配边界外的内存,造成内存越界
这章我们来讲下内存泄露、以及排查内存泄露的方法
内存分配以及回收
我们的内存主要分为以下部分、堆、栈、只读端、数据段、内存映射段。
- 栈:主要存放局部变量,由系统统一管理,所以不需要主动回收内存,一旦程序的作用域超过局部变量,就需要在堆中动态分配内存,在栈中的内存不会导致内存泄露
- 堆:程序通过malloc申请内存,除非程序退出否则申请的内存不会释放。这部分内存会导致内存泄露
- 只读段:保存程序的代码和常量,由于不需要继续申请内存,这部分会导致引起内存泄露
- 数据段:保存静态变量和全局变量,由于申请时候已经知道了大小所以也不需要释放,这部分会导致引起内存泄露
内存映射段:保存动态链接库和共享内存,由于共享内存的存在,
综上,堆、和内存映射段会导致内存泄露
内存泄漏的危害非常大,这些忘记释放的内存,不仅应用程序自己不能访问,系统也不能把它们再次分配给其他应用。内存泄漏不断累积,甚至会耗尽系统内存。虽然oom会Kill程序,但是在kill程序前会有很多严重的问题
如何定位内存泄露
我们可以使用bcc-tools下的memleak,如图下面就是一个简单的内存泄露场景,child会分配内存而且没有回收
1 | $ docker cp app:/app /app |
解决后的如下面所示
1 | # 重新执行 memleak工具检查内存泄漏情况 |
由mMemleak在centos中需要内核4.1以上支持,所以在老系统中我们用到valgrind的memcheck
1 | valgrind --tool=memcheck --leak-check=summary ./xxx-api |
上面的definitely lost代表必然的内存泄露,他包括indirectly【非直接】和directly【直接俩种, possibly lost是可能的内存泄露。我们只需要查看definitely lost即可