一文大白话讲清楚内存泄漏和应对策略
1. 啥是内存
- 这个相信大家都应该明白,就是计算机配给程序运行储存变量的一个存储器。我们经常会说我们运行内存是4G,8G就是这个道理,
- 我们的程序在运行时,会创建很多的变量存储在内存中。
2. 啥叫泄露
- 你创建一个变量,内存就给你分配一个空间,正常情况下,这个变量如果你用完了,我们就应该从内存中销毁。可以有些情况下你没销毁掉,这样内存就被占用的越来越多,这就算是内存泄漏了。
- 那么问题来了,我怎么释放变量所占用的内存,什么时间释放
3.什么时候释放
- 一句话,就是变量不再使用的时候
- 那问题来了怎么知道他不在被使用了呢
3.1 标记清除
- 当变量进入执行环境,就标记这个变量“进入环境”
- 当变量离开环境时,标记这个变量“离开环境”
3.2 引用计数
- 语言引擎有一张“变量引用表”,记录标量被引用的次数,如果被引用的次数是0,则说明不再使用了
3. 怎么回收内存-内存回收机制
- 无法两种,一种你自己手动调用方法清除
- 一种语言引擎自动回收
3.1 手动回收
char * buffer;
buffer = (char*) malloc(42);
// Do something with buffer
free(buffer);//手动释放内存
3.2自动回收
- javascript语言具有自动回收内存的机制。
- 垃圾收集器会定期(周期性)找出那些不在继续使⽤的变量,然后释放其内存
4. 都有自动回收机制了,为啥还会出现内存泄漏
- 很简单,上面说了,变量不用了,才会被回收。现在内存泄露了,说明回收不了,为啥回收不了,变量被持续占用呗。
- 那什么情况下会被持续占用呢
- 闭包 。不懂闭包的看我这篇文章 https://blog.csdn.net/xiaobangkeji/article/details/144705161
function bindEvent() {
var obj = document.createElement('XXX');
var unused = function () {
console.log(obj, '闭包内引⽤obj obj不会被释放');
};
obj = null;
}
- 定时器的残留
var someResource = getData();
setInterval(function() {
var node = document.getElementById('Node');
if(node) {
node.innerHTML = JSON.stringify(someResource));
}
}, 1000);
- DOM元素删除操作后遗留DOM变量等
const refA = document.getElementById('refA');
document.body.removeChild(refA);
console.log(refA, 'refA');
refA = null;
console.log(refA, 'refA');
5.内存泄露的应对策略