プログラミング基礎概念

メモリ管理 めもりかんり

ヒープスタックガベージコレクションメモリリークポインタ仮想メモリ
メモリ管理について教えて

簡単に言うとこんな感じ!

プログラムが使う「作業台のスペース」を上手にやりくりする仕組みだよ!必要なときにスペースを確保して、使い終わったらきちんと片付ける——それをやってくれるのがメモリ管理なんだ。片付けをサボると「メモリリーク」っていう問題が起きて、最終的にプログラムがクラッシュしちゃうってこと!


メモリ管理とは

メモリ管理(Memory Management)とは、プログラムの実行中にコンピューターのメインメモリ(RAM)をどのように割り当て・使用・解放するかをコントロールする仕組みのことです。プログラムは動作するたびに「変数の値」「関数の呼び出し履歴」「処理中のデータ」などを一時的にメモリへ書き込みながら動いており、この作業領域の管理が適切でないとシステム全体に悪影響が出ます。

メモリ管理はOSレベルとアプリケーションレベルの両方で行われます。OSが提供する仮想メモリの仕組みにより、各プログラムは「自分専用のメモリ空間が丸ごとある」かのように振る舞えます。その一方で、プログラムの開発言語ごとに「手動管理(C言語など)」と「自動管理(JavaPythonなど)」の2つのアプローチがあり、どちらを採用するかがシステムの安定性・パフォーマンスに大きく影響します。

ビジネス上の観点では、メモリ管理の設計が悪いシステムは長時間稼働すると徐々に遅くなる・突然落ちるといった障害を引き起こします。システム選定や開発委託時に「メモリリークの対策はどうしているか」を確認することは、品質評価の重要な視点です。


メモリの構造と種類

プログラムが使うメモリ空間は、用途ごとにいくつかの領域に分かれています。

領域名別名用途管理方法
スタック(Stack)自動変数領域関数の引数・ローカル変数・呼び出し履歴自動(関数終了時に自動解放)
ヒープ(Heap)動的メモリ領域プログラム実行中に動的に確保するデータ手動 or GCによる管理
静的領域(BSS/Data)グローバル変数領域グローバル変数・静的変数プログラム終了まで保持
コード領域(Text)テキストセグメントプログラムの命令コード自体読み取り専用・変更不可

覚え方:スタックは「皿洗いの積み重ね」

スタックは「後から積んだものを先に取り出す(LIFO:Last In First Out)」構造です。食器洗いで皿を積み上げるイメージ——一番上(最後に置いた皿)を先に使う、と覚えましょう。関数が呼ばれるたびに情報を積み上げ、関数が終わると自動的に一番上から取り除かれます。

手動管理 vs 自動管理(GC)

方式代表言語メリットデメリット
手動管理C, C++高速・細かい制御が可能メモリリークやバッファオーバーフローリスク
ガベージコレクション(GC)Java, Python, Go, C#安全・開発効率が高いGC実行時に一時的な処理停止(Stop-the-World)が起きることがある
所有権モデルRustGCなしで安全・高速学習コストが高い

歴史と背景

  • 1950年代:初期のコンピューターはメモリが数KBしかなく、プログラマーが手動でメモリアドレスを直接管理していた
  • 1960年代:IBMのOS/360など、OSがメモリを複数プログラムに分配する「多重プログラミング」が登場
  • 1969年頃仮想メモリの概念が実用化。物理的なRAMより大きいメモリ空間をプログラムに提供できるようになった
  • 1960年代後半:Lispインタープリターで世界初のガベージコレクター(GC)実装される
  • 1980〜90年代:C言語の普及により手動メモリ管理が主流となり、malloc()/free()による管理が一般的に
  • 1995年:JavaがGCを採用した言語として登場。「メモリ管理をプログラマーが意識しなくてよい」時代の幕開け
  • 2000年代〜:Python・RubyPHPなどのスクリプト言語がGCを標準装備。Webアプリ開発では手動管理がほぼ不要に
  • 2015年Rustが登場。「所有権(Ownership)」という新概念でGCなしに安全なメモリ管理を実現

メモリ管理の方式と仮想メモリの仕組み

仮想メモリ(Virtual Memory)は、OSが各プログラムに「仮想的な連続メモリ空間」を提供する技術です。実際の物理RAM上での配置とは切り離されているため、複数のプログラムが互いに干渉せず安全に動作できます。

プロセスA の 仮想メモリ空間 コード領域 静的・グローバル変数 ヒープ ↑ (未使用領域) スタック ↓ 物理メモリ(RAM) 実際のアドレス空間 OS カーネル領域 プロセスA コード プロセスA ヒープ プロセスB コード プロセスA スタック プロセスB ヒープ MMU / OS (仮想→物理アドレス変換) ページテーブル 仮想アドレスを 物理アドレスに マッピング プロセスは独立した仮想空間を持ち、互いに干渉しない

GC(ガベージコレクション)の主なアルゴリズム

アルゴリズム仕組み採用例
参照カウント方式オブジェクトへの参照数をカウントし、0になったら解放Python, Swift
マーク&スイープ到達可能なオブジェクトに印をつけ、印のないものを一括削除Java, JavaScript
世代別GCオブジェクトを「若い世代」「老い世代」に分けて効率的に回収Java(G1GC), Python
トライカラーマーキング白・グレー・黒の3色で到達可能性を管理し並行処理に対応Go

よくある問題:メモリリークとバッファオーバーフロー

メモリ管理の不備から生じる代表的な問題を押さえておきましょう。

問題名何が起きるか発生しやすい言語実例
メモリリーク確保したメモリを解放し忘れ、使用量が増え続けるC, C++(手動管理)長時間稼働サーバーが徐々に重くなる
バッファオーバーフロー確保した領域を超えてデータを書き込むC, C++セキュリティ脆弱性の原因になることも
ダングリングポインタ解放済みのメモリを参照し続けるC, C++予測不能なクラッシュ・データ破壊
二重解放(Double Free)同じメモリ領域を2回解放するC, C++プログラムのクラッシュ
GC停止(STW)GC実行中に全スレッドが一時停止するJava, Pythonリアルタイム処理の遅延
【メモリリークのイメージ】

時間 →
t=0  [使用中: 10MB ][ 空き: 990MB ]
t=1h [使用中: 150MB][ 空き: 850MB ]
t=6h [使用中: 800MB][ 空き: 200MB ]  ← だんだん重くなる
t=8h [使用中: 1000MB][ 空き: 0MB ]  ← クラッシュ!

関連する規格・RFC

規格・RFC番号内容
RFC 7525TLS利用ガイドライン(メモリ安全性はセキュリティプロトコル実装にも影響)
POSIX.1-2017malloc() / free() / mmap() などのメモリ管理APIの標準仕様(IEEE Std 1003.1)

関連用語

  • スタック — 後入れ先出し(LIFO)のデータ構造。関数呼び出し時のローカル変数管理に使われる
  • ヒープ — 動的に確保・解放できるメモリ領域。GCやmalloc()が管理する
  • ガベージコレクション — 不要になったメモリを自動回収する仕組み
  • ポインタ — メモリアドレスを直接指し示す変数。C/C++における手動メモリ管理の中心
  • 仮想メモリ — OSが提供する論理的なメモリ空間。物理RAMより大きい空間を使える
  • プロセス — OSが管理する実行単位。独立したメモリ空間を持つ
  • OSI参照モデル — ネットワーク通信の層構造モデル(メモリ管理はOS層と密接に関係)
  • Rust — 所有権モデルでGCなしの安全なメモリ管理を実現するプログラミング言語