メモリリークとは(全体像)
プログラムはメモリを借りて(確保して)使い、終わったら返す(解放する)のが正しい使い方。この「返す」を忘れると、使えないメモリがたまっていく。これがメモリリークだ。
身近にたとえると、図書館の本の借りっぱなし。借りて(確保)読み終わったら返す(解放)のが正しいが、返し忘れが続くと、棚から本がどんどん減って、やがて誰も借りられなくなる。
押さえるのは、リークはすぐクラッシュするとは限らないこと。少しずつたまるので、長く動かして初めて問題が表に出ることが多い。
詳しく:原因と「GCでも起きる」だけ覚えれば戦える
ここが記事の心臓部。まず主な原因を見ましょう。
メモリリークの主な原因
| 原因 | 内容 |
|---|---|
| 解放忘れ | C/C++で確保(malloc/new)したのに返さない |
| 循環参照 | AがB、BがAを参照し合い、どちらも解放されない |
| 参照の保持 | グローバル変数などが参照を握りっぱなし |
ここで一番のひっかけが「GC(自動でメモリを回収するしくみ)のある言語ならリークしない」という誤解。GCがあっても、循環参照や参照の握りっぱなしでリークは起きる。GCを過信しないのがポイント。
検出と予防には、次のような手段がある。
検出ツールと予防策
| 区分 | 代表例 |
|---|---|
| 検出ツール | Valgrind(Linux)、AddressSanitizer |
| 予防(C++) | RAII(スコープを抜けたら自動で返す)、スマートポインタ |
| 予防(Java) | try-with-resources(使い終わったら自動で閉じる) |
RAIIは、処理のまとまり(スコープ)を抜けると自動でメモリを返す書き方。スマートポインタ(unique_ptr・shared_ptrなど)は、誰がメモリの持ち主かをはっきりさせて、返し忘れを防ぐ。
わかりやすく言い換えると
要するに、図書館の本でイメージするとラクです。
①メモリリーク … 借りた本を返し忘れて、棚の本が少しずつ減っていく
②循環参照 … AさんとBさんがおたがいの本を持ち合って、どちらも返却箱に入らない
③RAII・スマートポインタ … 「席を立ったら自動で返却」「持ち主を札で明示」のしくみ
つまり、「リークは返し忘れの蓄積」「GCでも循環参照で起きる」、この2点が試験の急所です。
試験のツボ
🔴 一番出る:メモリリークの正体と原因
①使い終わったメモリを返し忘れて、使えないメモリがたまる現象
②主な原因は解放忘れ・循環参照・参照の握りっぱなし
🔴 次に出る:GCでも起きる
①GC(自動回収)のある言語でも、循環参照などでリークは起きる
②すぐクラッシュせず、長時間の稼働で表に出ることが多い
🟡 押さえると安定:検出と予防
①検出ツールはValgrind・AddressSanitizerなど
②予防はRAII・スマートポインタ(C++)、try-with-resources(Java)
よくある間違い
①「GCのある言語ならメモリリークは絶対に起きない」→ ✗ GCがあっても、循環参照や参照の握りっぱなしでリークは起きる。
②「メモリリークは起きたらすぐにクラッシュする」→ ✗ 少しずつたまるので、長く動かして初めて表に出ることが多い。
③「メモリリークはメモリの読み取りが速くなる現象である」→ ✗ 逆で、使えるメモリが減っていき、いずれ不足する現象。
試験での出題パターン
実際の問題でたしかめてみよう。
オリジナル問題1(メモリリークの正体)
メモリリークに関する次の記述のうち、正しいものはどれか。
- メモリリークはメモリの読み書きがいつもより速くなる、歓迎すべき現象だとされているものだ
- メモリリークは確保したメモリを画面に表示する機能のことを指すものだとされている
- メモリリークは音漏れのことで、プログラムのメモリ管理とは関係がないものだとされている
- メモリリークは使い終わったメモリを返し忘れて、使えないメモリがたまっていく現象である
解答は 4 ですよ。
メモリリークは、使い終わったメモリを返し忘れて、使えないメモリがたまっていく現象ですね。たまり続けるといずれメモリが足りなくなります。図書館の本の借りっぱなしと同じイメージです。
選択肢1の「速くなる」、選択肢2の「画面に表示する機能」、選択肢3の「音漏れ」はどれも誤りですよ。
| 選択肢 | 判定 | 理由 |
|---|---|---|
| 1 | ✗ | 速くならず使えるメモリが減る |
| 2 | ✗ | 表示する機能ではない |
| 3 | ✗ | 音漏れではない |
| 4 | ✓ | 返し忘れで使えないメモリがたまる |
オリジナル問題2(GCでも起きる)
GC(自動でメモリを回収するしくみ)とメモリリークについて、正しいものはどれか。
- GCのある言語でも、循環参照や参照の握りっぱなしによってメモリリークは起きることがある
- GCのある言語ではメモリリークは絶対に起きず、循環参照も自動で必ず解消されるものだとされる
- GCはメモリをわざと漏らすしくみのことで、リークを増やすために使われるものだとされている
- GCは画面の自動更新のしくみのことで、メモリの回収とは無関係なものだとされているものだ
解答は 1 ですよ。
GC(自動回収)があっても、循環参照や参照の握りっぱなしによってメモリリークは起きることがありますね。GCがあるから安全、と過信しないのがポイントです。
選択肢2の「絶対に起きない」、選択肢3の「わざと漏らすしくみ」、選択肢4の「画面の自動更新」はどれも誤りですよ。
| 選択肢 | 判定 | 理由 |
|---|---|---|
| 1 | ✓ | 循環参照などでGCでも起きる |
| 2 | ✗ | GCでも起きることがある |
| 3 | ✗ | わざと漏らすしくみではない |
| 4 | ✗ | 画面の更新とは無関係 |
オリジナル問題3(検出と予防)
メモリリークの検出・予防に関する次の記述のうち、正しいものはどれか。
- メモリリークは予防も検出もまったくできず、起きたら手の打ちようがないものだとされている
- メモリリークの予防にはRAIIやスマートポインタ、検出にはValgrindが使えるとされる
- メモリリークの検出はキーボードの掃除で行い、予防はモニタの拭き取りで行うものだとされる
- メモリリークの予防はメモリをいっさい使わないことだけで、ほかに方法はないものだとされている
解答は 2 ですよ。
予防には、スコープを抜けたら自動で返すRAIIや、持ち主を明示するスマートポインタが使えますね。検出にはValgrindやAddressSanitizerなどのツールがあります。
選択肢1の「手の打ちようがない」、選択肢3の「キーボードの掃除」、選択肢4の「メモリを一切使わない」はどれも誤りですよ。
| 選択肢 | 判定 | 理由 |
|---|---|---|
| 1 | ✗ | 予防も検出もできる |
| 2 | ✓ | 予防はRAII等・検出はValgrind等 |
| 3 | ✗ | 物理的な掃除とは無関係 |
| 4 | ✗ | メモリは使ってよい・仕組みで防ぐ |
まとめ
押さえどころ
- 🔴 メモリリーク = 使い終わったメモリを返し忘れ、使えないメモリがたまる現象。原因は解放忘れ・循環参照・参照の握りっぱなし。
- 🔴 GCでも起きる = 自動回収のある言語でも、循環参照などでリークは起きる。すぐクラッシュせず長時間で表に出る。
- 🟡 検出と予防 = 検出はValgrind等、予防はRAII・スマートポインタ(C++)、try-with-resources(Java)。
次に学ぶ
- ガーベッジコレクション ── 使い終わったメモリを自動で回収するしくみ。リーク対策の中心。
- メモリ割当戦略 ── どの空きを渡すか決めるやり方。メモリ不足や断片化の理解につながる。
執筆: SikakuQuest編集部