0


< 今日份知识点:谈谈内存泄漏 及 在 Javascript 中 针对内存泄漏的垃圾回收机制 >

文章目录


💬 前言

说起

“ 内存泄漏 ”

,科班出身的卷王们应该第一时间会想到 C语言的指针,对内存的分配 或者 其他操作。程序需要运行,必然会占用内存,就好比我们在电脑上运行程序,就必须向运行的软件程序提供内存,它才能运行。

程序运行会生成对应的服务进程,对于一些持续的服务进程,它会持续的占用内存,但是当服务运行一个来回时,如果上次运行申请的内存,没有得到及时的释放,就会导致

“ 内存泄漏 ”

通俗点说,就是指被遗漏的内存持续占用堆积

这样的结果显而易见,会造成服务性能降低,严重会导致服务卡顿等现象。所以这里就需要我们去了解 “ 内存泄漏 ” 的原理,避免出现内存持续占用的情况! 接下来,就由小温带大家去了解 “ 内存泄漏 ” 相关的知识点吧!


👉 一、“ 内存泄漏 ”简述

内存泄漏(

Memory leak

)是在计算机科学中,由于疏忽或错误造成

程序未能释放已经不再使用的内存

并非指内存在物理上的消失,而是应用程序分配某段内存后,由于设计错误,导致在

释放该段内存之前就失去了对该段内存的控制,从而造成了内存的浪费

正如前言所述,程序的运行需要内存。只要程序提出要求,操作系统或者运行时就必须供给内存

对于

持续运行的服务进程

,必须及时

释放

不再用到的内存。否则,内存占用越来越高,轻则影响系统性能,重则导致进程崩溃

在这里插入图片描述

C语言

为例,由于 C语言 是 手动管理内存,如果程序设计不当,是非常容易导致

“ 内存泄漏 ”

// 申请内存char* buffer;
buffer =(char*)malloc(42);// Do something with buffer...// 使用free方法释放内存free(buffer);

上面案例中,在C语言中,使用

malloc

方法用来申请内存,使用完毕之后,必须自己用

free

方法释放内存。

这种

手动管理内存

的方式非常麻烦,在申请内存的变量多时,操作累赘重复。所以为了提高编写效率,现在大多数语言提供

自动内存管理

,减轻程序员的负担,这被称为

" 垃圾回收机制 "

👉 二、 垃圾回收机制

Javascript

具有自动垃圾回收机制(

GC:Garbage Collecation

),也就是说,执行环境会负责管理

代码执行过程中使用的内存

,自动进行释放等操作!

> 原理

垃圾收集器会定期(

周期性

)找出那些不在继续使用的变量,然后释放其内存。

那么,可能会有卷王疑惑了,垃圾收集器怎么知道我哪些变量还要使用,哪些变量在指定位置不需要使用了呢? 这就引出了 “

垃圾回收机制

” 的实现方式了,内容如下:

通常情况下有两种实现方式:

  • 标记清除 : 通过判断变量进出执行环境,标记变量在指定位置所处的状态,若变量已离开执行所处的环境,此变量将等待 “ 垃圾回收
  • 引用计数 : 通过判断变量被引用的次数,判断此变量是否任需使用。如果引用次数为 “ 0 ”,那么此变量占用的内存将会被回收!

> 实现方式(详)

① 标记清除

判断原理 : 当变量进入执行环境时,就标记这个变量为“

进入环境

“。进入环境的变量所占用的内存就不能被释放,当变量离开环境时,则将其标记为“

离开环境

垃圾回收程序运行的时候,会标记内存中存储的所有变量。然后,它会将所有在上下文中的变量,以及被在上下文中的变量引用的变量的标记去掉。

垃圾回收机制 - 标记清除

在此之后再被加上标记的变量就是待删除的了,原因是任何在上下文中的变量都访问不到它们了

随后

垃圾回收程序

做一次内存清理,销毁带标记的所有值并收回它们的内存。

优点:

  • 实现简单,标记情况无非是打与不打的两种情况,通过二进制(0和1)就可以为其标记。
  • 能够回收循环引用的对象
  • v8引擎使用最多的算法。

缺点:

在清除垃圾之后,剩余对象的内存位置是不变的,就会导致空闲内存空间不连续。这样就出现了

内存碎片

,并且由于剩余空间不是整块,就需要考虑内存分配的问题。

举个例子:

var m =0,n =19// 把 m,n,add() 标记为进入环境。add(m, n)// 把 a, b, c标记为进入环境,当此方法体运行完,代表内部的局部变量离开环境。
console.log(n)// a,b,c标记为离开环境,等待垃圾回收。functionadd(a, b){
  a++let c = a + b
  return c
}

② 引用计数

语言引擎有一张"

引用表

",保存了内存里面所有变量引用的内存资源(通常是各种值)的引用次数。如果一个值的引用次数是

0

,就表示这个值不再用到了,因此可以将这块内存释放。

tips: 如果一个值不再需要了,引用数却不为0,垃圾回收机制无法释放这块内存,从而导致内存泄漏。

const arr =[1,2,3,4];// arr 占用的内存泄漏
console.log('hello world');

上面代码中,数组arr, 存储的 [1, 2, 3, 4] 是一个值,会占用内存。变量arr是仅有的对这个值的引用,因此引用次数为

1

。尽管后面的代码没有用到arr,它还是会持续占用内存。

如果需要这块内存被垃圾回收机制释放,只需要设置如下:

arr =null

通过设置arr为null,就解除了对数组[1,2,3,4]的引用,引用次数变为 0,就会立刻被垃圾回收了。

优点:

  • 引用计数为零时,发现垃圾立即回收
  • 最大限度减少程序暂停

缺点:

  • 无法回收循环引用的对象
  • 空间开销比较大

👉 三、常见的几种内存泄漏的情景

①在某个局部代码块中,出现全局变量操作

functionfoo(arg){
    bar ="this is a hidden global variable";}

② 全局变量可能由 this 创建

functionfoo(){this.variable ="potential accidental global";}// foo 调用自己,this 指向了全局对象(window)foo();

tips:上述使用严格模式,可以避免意外的全局变量

③ 定时器也常会造成内存泄露

var someResource =getData();setInterval(()=>{var node = document.getElementById('Node');if(node){// 处理 node 和 someResource
        node.innerHTML =JSON.stringify(someResource));}},1000);

如果id为Node的元素从DOM中移除,该定时器仍会存在,同时,因为回调函数中包含对

someResource

的引用,定时器外面的

someResource

也不会被释放

④ 包括之前所说的闭包,维持函数内局部变量,不能及时释放,一样会造成内存泄漏

functionbindEvent(){var obj = document.createElement('XXX');varunused=function(){
    console.log(obj,'闭包内引用obj obj不会被释放');};
  obj =null;// 解决方法}

⑤ 没有清理对DOM元素的引用同样造成内存泄露

const refA = document.getElementById('refA');
document.body.removeChild(refA);// dom删除了
console.log(refA,'refA');// 但是还存在引用能console出整个div 没有被回收
refA =null;
console.log(refA,'refA');// 解除引用

**⑥ 使用事件监听

addEventListener

监听的时候,在不监听的情况下使用

removeEventListener

取消对事件监听**

以上为日常开发中,比较常见的内存泄漏场景,需要在平时开发中加以留意!

> 小结

虽然JavaScript提供了一套

垃圾回收机制

, 但是并不代表不用关注

内存泄露

。那些很占空间的值,一旦不再用到,需要及时检查是否还存在对它们的引用。如果是的话,就必须手动解除引用,这是日常开发中,需要注意的JavaScript书写规范!

今天的内容就此结束,如果觉得对你有帮助的话,不妨点点赞,支持一下小温呀!


📃 参考文献

  • JavaScript 内存泄漏教程 - 阮一峰
  • 详解JavaScript的垃圾回收机制 - 1900’‘’'s 88 keys

往期内容 💨

🔥 < 今日份知识点:浅述对 “ Vue 插槽 (slot) ” 的理解 以及 插槽的应用场景 >

🔥 <恢复更新进度ing:今天浅聊一下前端CSS样式 及 书写的规范 >

🔥 < 每日份知识快餐:axios是什么?如何在Vue中 封装 axios ? >

🔥 < 今日份知识点:web常见的攻击方式(网络攻击)有哪些?如何预防?如何防御呢 ? >


本文转载自: https://blog.csdn.net/MrWen2395772383/article/details/125486988
版权归原作者 技术宅小温 所有, 如有侵权,请联系我们删除。

“< 今日份知识点:谈谈内存泄漏 及 在 Javascript 中 针对内存泄漏的垃圾回收机制 >”的评论:

还没有评论