是什么?
程序使用 new / malloc / realloc 动态存储分配函数 向系统在堆申请了内存空间,使用完后应该调用 free / delete 释放该内存块。
但因为种种原因使用完毕后未释放,导致这个不使用的对象一直占据内存单元,造成系统将不能再把它分配给需要的程序。
危害
系统分配给每个应用的内存资源都是有限的,内存泄漏堆积危害很大。
- 频繁GC:内存泄漏导致其他组件可用的内存变少后,一方面会使得GC的频率加剧,再发生GC的时候,所有进程都必须等待,GC的频率越高,用户越容易感应到卡顿。另一方面内存变少,可能使得系统额外分配给该对象一些内存,而影响整个系统的运行情况。
- 导致程序运行崩溃:一旦内存不足以为某些对象分配所需要的空间,将会导致程序崩溃。
常见内存泄漏场景
- 变量不合理作用域(闭包:回调、计时器)
- DOM 引用
- 连接(数据库连接、网络连接和IO连接)未关闭
等等等等
解决方式
总之就是闭源(良好的代码书写习惯)节流(释放内存)
- 在 JavaScript 文件开头添加
use strict
,使用严格模式。在严格模式下解析 JavaScript 可以防止意外的全局变量 - 赋值为 null 或者重新分配
- close()
- document.body.removeChild()
监测
使用内存监视工具收集一段时间内的堆栈内存信息,观测增长趋势,来确定是否有内存泄漏。
以下内容来自参考文章5
:
Linux 常用的内存泄露检测工具:
mtrace、memwatch、valgrind、debug_new
.
以上的这些分析工具,所使用的方法大致分为以下几种:
- 注册内存分配/释放钩子函数(hook)。在 Linux 下可以
malloc_hook, free_hook
等5个钩子函数,在 Windows 下可以注册_CrtSetAllocHook
钩子函数,这样在分配内存的时候就可以捕获这一请求并加以处理。Visual Leak Detecter
和mtrace
使用此方式。- 使用宏定义替换。将用户代码中的 malloc、free 替换为宏定义的
mwMalloc(sz, __FILE__, __LINE__)
等自定义函数,从而跟踪内存请求,memwatch 即使用此方式。- 操作符重载。此方法仅用于 C++ 语言中,通过重载 new、delete 操作符来实现跟踪内存请求,重载后的操作符类似于钩子函数意义。
debug_new
采用此方式。
这些工具的内存检测方式:
- 维护一个内存操作链表,当有内存申请操作时,将其加入此链表中,当有释放操作时,从申请操作从链表中移除。如果到程序结束后此链表中还有内容,说明有内存泄露了;如果要释放的内存操作没有在链表中找到对应操作,则说明是释放了多次。使用此方法的有内置的调试工具,
Visual Leak Detecter、mtrace、memwatch、debug_new
。- 模拟进程的地址空间。仿照操作系统对进程内存操作的处理,在用户态下维护一个地址空间映射,此方法要求对进程地址空间的处理有较深的理解。因为 Windows 的进程地址空间分布不是开源的,所以模拟起来很困难,因此只支持 Linux。采用此方法的是
valgrind
。
相关文章
网友评论