メモリレイアウト

プログラムのメモリ空間の構造で、スタック、ヒープ、コード領域、データ領域から構成される

低レベルメモリ管理

メモリレイアウトとは

プログラムのメモリ空間は、コード領域、データ領域、ヒープ、スタックの 4 つの領域で構成される。JavaScript 開発者が直接操作することは少ないが、パフォーマンスやメモリリークの理解に重要。

メモリ領域

メモリ領域を図で示す。

高アドレス ┌──────────────┐
          │   スタック ↓   │ ← 関数の引数、ローカル変数
          │              │
          │   ↓ 成長方向  │
          │              │
          │   ↑ 成長方向  │
          │              │
          │   ヒープ ↑    │ ← 動的に確保されるオブジェクト
          ├──────────────┤
          │   データ領域   │ ← グローバル変数、定数
          ├──────────────┤
          │   コード領域   │ ← 実行可能なコード
低アドレス └──────────────┘
領域 内容 管理
スタック 関数の引数、ローカル変数 自動 (LIFO)
ヒープ オブジェクト、配列、文字列 GC or 手動
データ グローバル変数、定数 コンパイル時に確定
コード 実行可能な命令 読み取り専用

スタック vs ヒープ

スタックとヒープの違いを以下にまとめる。

観点 スタック ヒープ
速度 高速 (ポインタ移動のみ) 低速 (アロケーション)
サイズ 小さい (数 MB) 大きい (数 GB)
管理 自動 (関数終了で解放) GC or 手動
格納データ プリミティブ、参照 オブジェクト、配列

V8 (Node.js) のメモリ

V8 (Node.js) のメモリのコード例を示す。

// スタック: プリミティブ値と参照
const x = 42;           // スタックに 42 を格納
const obj = { a: 1 };   // スタックに参照、ヒープにオブジェクト

// ヒープ: オブジェクト
// V8 のヒープは Young Generation と Old Generation に分かれる

LambdaMemorySize はヒープ、スタック、OS のオーバーヘッドを含む。CPU も比例して割り当てられるため、メモリを増やすと処理速度も向上する。

スタックオーバーフロー

スタックオーバーフローのコード例を示す。

// ❌ 無限再帰 → スタックオーバーフロー
function infinite(): number { return infinite(); }
// RangeError: Maximum call stack size exceeded

// ✅ 末尾再帰最適化 (一部の環境) or ループに変換
function factorial(n: number, acc = 1): number {
  if (n <= 1) return acc;
  return factorial(n - 1, n * acc);
}

メモリリークの検出

メモリリークの検出の例を示す。

# Node.js のヒープ使用量を確認
node -e "console.log(process.memoryUsage())"
# { rss: 30MB, heapTotal: 7MB, heapUsed: 5MB, external: 1MB }

メモリレイアウトについては関連書籍でも詳しく扱われている。

この記事は役に立ちましたか?

関連用語

関連する記事