Javascriptにはメモリ リークが発生しますか?もしそうなら、それを避けるにはどうすればよいでしょうか?最近何人かが同様の質問をしてきたことから、この部分の内容を体系的に研究した人は誰もいないと思われるため、数年前にまとめた情報を共有するつもりです。
まず、少なくとも IE6 では、JavaScript の記述方法によってはメモリ リークが発生することは確実に言えます。したがって、IE6 が廃止されることを拒否している今日でも、関連する知識を理解する必要があります (ただし、ほとんどの場合、js によって引き起こされるメモリ リークはコンピューターの速度を低下させる主な原因ではありません)。関連する研究は主に 2005 年から 2007 年に集中しています。当時に研究した友人がいる場合は、無視してください。
フロントエンド開発者として、これらの問題を理解するには、その問題が何であるか、そしてその理由を知る必要があります。 したがって、js のメモリ リークについて説明する前に、なぜメモリ リークが発生するのかを説明します。
メモリ リークについて話すときは、メモリの割り当て方法について話さなければなりません。メモリを割り当てる方法は 3 つあります。
1. 静的割り当て: 静的変数とグローバル変数の割り当て形式。部屋をプログラムとして考えると、静的に割り当てられたメモリは部屋の耐久性のある家具のように考えることができます。戸棚を毎日ゴミとして窓から捨てる人はいないため、通常、放出してリサイクルする必要はありません。
2. 自動割り当て: スタック上のローカル変数にメモリを割り当てる方法。スタック内のメモリは、コード ブロックが終了するときに、pop 操作で自動的に解放できます。
これは、何かをするために部屋に来た人が、用事を済ませると勝手に退去し、退室すると占有したスペースが自動的に解放されるのと同じです。
3. 動的割り当て: データを保存するためにヒープ内のメモリ空間を動的に割り当てる方法。つまり、プログラムの実行中に malloc または new を使用して適用されたメモリは、free または delete を使用して自分で解放する必要があります。動的メモリの寿命はプログラマによって決定されます。解放を忘れると、必然的にメモリリークが発生します。この場合、ヒープ内のメモリ ブロックは、私たちが毎日使用するナプキンのようなものです。使用後はゴミ箱に捨てなければなりません。そうしないと家が散らかってしまいます。したがって、怠け者は、一緒にお掃除してくれる家庭用ロボットを持つことを夢見ています。ソフトウェア開発において、メモリを解放するのが面倒な場合は、同様のロボットも必要になります。実際には、特定のアルゴリズムによって実装されたガベージ コレクタです。 JavaScript のメモリ リークを引き起こすのは、まさにガベージ コレクション メカニズム自体のいくつかの欠陥です。
数年前、ゴミ収集の仕組みについて詳しく説明した「ゴミリサイクルの興味深い歴史」という記事を読みました。
多くの高級車がセールスポイントとして使用しているスーパーチャージャー技術が、1910 年代にメルセデス・ベンツで実際に採用されたのと同じように、ゴミのリサイクル技術も古くから存在しています。 1960 年頃に MIT で誕生した Lisp 言語は、動的メモリ割り当てテクノロジに大きく依存した最初の言語でした。Lisp 内のほとんどすべてのデータは「テーブル」の形式で表示され、「テーブル」によって占有されるスペースはヒープ内にあります。動的に割り当てられます。 Lisp 言語の生来の動的メモリ管理機能では、Lisp 言語の設計者がヒープ内の各メモリ ブロックの自動解放の問題を解決する必要があります (そうしないと、Lisp プログラマはプログラム内の無数の free または delete ステートメントに圧倒されてしまうことは避けられません)。これはガベージコレクション技術の誕生と発展に直接つながりました。
最も基本的な 3 つのガベージ コレクション アルゴリズムも、当時一緒に登場しました。一つずつ見ていきましょう。
参照カウント アルゴリズム: これが最初に思い浮かぶ方法かもしれません。比喩的に言えば、参照カウントは次のように理解できます。家にはたくさんのホワイトペーパーがあり、これらのペーパーは思い出のようなものです。記憶を使うことは、これらの紙に書くことに似ています。メモリは自由に使えますが、紙を使う人は必ず紙の隅にカウント1を書かなければなりません。2人で同時に使うとカウントが0になります。 2、など。人間が紙を使い終わると、隅にあるカウントを1つ減らす必要があります。このようにして、カウントが0になると、ガベージコレクションの条件が満たされ、脇に待機していたロボットがすぐに紙をコーナーに投げ込みます。ゴミ箱。参照カウンタベースのガベージ コレクタはより高速に実行され、プログラムの実行を長時間中断することがなく、リアルタイムで実行する必要があるプログラムに適しています。ただし、参照カウンタはプログラム実行のオーバーヘッドを増加させます。同時に、このアルゴリズムには、循環参照が生成されるとメモリ リークが発生するという別の大きな問題があります。たとえば、2 つのオブジェクト a と b を作成します。このとき、a と b のカウントは両方とも 1 です。このとき、a の属性は b に、b の属性は a にポイントされます。参照関係では、a と b のカウントは両方とも 2 になります。プログラムが終了してスコープを出ると、プログラムは自動的に a のカウントを 1 ずつ減分します。最後に a のカウントは 1 のままであるため、a はゼロになりません。同様に、 b の最終カウントも 1 になり、b は解放されず、メモリがリークされるだけです。