前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >如何解决内存泄漏引发的血案

如何解决内存泄漏引发的血案

作者头像
零式的天空
发布2022-03-22 15:22:12
5050
发布2022-03-22 15:22:12
举报
文章被收录于专栏:零域Blog

之前做了一个谷歌浏览器的插件开发,它会打开一个链接,然后收集数据并上传。依次循环,但是跑的时间久了,内存就变得很高,然后浏览器就会变卡,慢慢的影响这个插件的运行,最后浏览器也会崩溃。

什么是内存泄漏

内存泄露是指一块被分配的内存既不能使用,又不能回收,直到浏览器进程结束。在 C++ 中,因为是手动管理内存,内存泄露是经常出现的事情。而现在流行的 C# 和 Java 等语言采用了自动垃圾回收方法管理内存,正常使用的情况下几乎不会发生内存泄露。浏览器中也是采用自动垃圾回收方法管理内存,但由于浏览器垃圾回收方法有 bug,会产生内存泄露。

自动垃圾收集是不能代替有效的内存管理的,特别是在大型,长时间运行的Web应用程序中。

内存泄漏的几种情况

1、Delete 一个 Object 的属性会让此对象变慢

代码语言:javascript
复制
var obj = {x: 'y'};
delete obj;  // 此时 obj 会成一个慢对象
obj.x;

var obj = {x: 'y'};
obj = null;  // 应该这样

2、闭包 1)在闭包中引入闭包外部的变量时,当闭包结束时此对象无法被垃圾回收(GC)。 2)闭包可以维持函数内局部变量,使其得不到释放。

代码语言:javascript
复制
var a = function() {
  var largeStr = new Array(1000000).join('x');
  return function() {
    return largeStr;
  }
}();

3、DOM 泄漏 当原有的 DOM 被移除时,子节点引用没有被移除则无法回收 当页面中元素被移除或替换时,若元素绑定的事件仍没被移除,在 IE 中不会作出恰当处理,此时要先手工移除事件,不然会存在内存泄漏。

代码语言:javascript
复制
var btn = document.getElementById("myBth");
btn.onclick = function() {
  document.getElementById("myDiv").innerHTML = 'test memory';
}

应改成下面:

代码语言:javascript
复制
var btn = document.getElementById("myBth");
btn.onclick = function() {
  btn.onclick = null;
  document.getElementById("myDiv").innerHTML = 'test memory';
}

4、Timers 计(定)时器泄漏 定时器也是常见产生内存泄露的地方

代码语言:javascript
复制
for(var i=0; i<90000; i++) {
  var obj = {
    callAgain: function() {
        var ref = this;
        var val = setTimeout(function(){
          ref.callAgain();
        },90000);
    }
  };
  obj.callAgain();
  // 虽然你想回收但是 timer 还在
  obj = null;
}

5、jquery 的 html() 函数 页面中还需要注意的一点是使用 jquery 的 html() 函数,该函数不是基于 innerHTML 实现的,大量使用同样也会导致系统性能下降。

6、使用事件委托代替事件注册 页面中如果元素过多,且需要为每个元素注册相同的 click 事件,这个时候我们优先考虑到使用委托机制,将需要注册的 click 事件注册到元素的上层或者顶层元素,这样我们就节省了大量的 click 注册事件。

7、自动类型装箱转换

代码语言:javascript
复制
var s = "test test";
alert(s.length);

s 本身是一个 string 而非 object,它没有 length 属性,所以当访问 length 时,JS 引擎会自动创建一个临时 String 对象封装 s,而这个对象一定会泄漏。这个 bug 匪夷所思,所幸解决起来相当容易,记得所有值类型做.运算之前先显示转换一下:

代码语言:javascript
复制
var s = "test test";
alert(new String(s).length);

调试内存

1、Timeline Chrome 自带的内存调试工具可以很方便的查看内存使用情况和内存泄漏: F12 -> Timeline -> Memory 点击 record 即可开始收集,点击弹出框的 Finish 即停止,然后会统计出 record 到 Finish 这一段时间内的内存使用情况。

2、Profiles Chrome 自带的 Profiles 可以记录当前的内存使用情况 F12 -> Profiles -> Take Heap Snapshot 点击 Take Snapshot 就可以拍下当前 JS 的 heap 快照。 注意:每次拍快照前,都会先自动执行一个 GC,所以在视图里的对象都是可及的。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2017-02-28,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 什么是内存泄漏
  • 内存泄漏的几种情况
  • 调试内存
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档