メモリリークとは?使い終わったメモリを返し忘れて

公開: 更新: カテゴリ: テクノロジ系

30秒で結論

メモリリークとは(全体像)

プログラムはメモリを借りて(確保して)使い、終わったら返す(解放する)のが正しい使い方。この「返す」を忘れると、使えないメモリがたまっていく。これがメモリリークだ。

身近にたとえると、図書館の本の借りっぱなし。借りて(確保)読み終わったら返す(解放)のが正しいが、返し忘れが続くと、棚から本がどんどん減って、やがて誰も借りられなくなる。

押さえるのは、リークはすぐクラッシュするとは限らないこと。少しずつたまるので、長く動かして初めて問題が表に出ることが多い。


詳しく:原因と「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(メモリリークの正体)

📝 オリジナル問題 1 メモリリークの正体

メモリリークに関する次の記述のうち、正しいものはどれか。

  1. メモリリークはメモリの読み書きがいつもより速くなる、歓迎すべき現象だとされているものだ
  2. メモリリークは確保したメモリを画面に表示する機能のことを指すものだとされている
  3. メモリリークは音漏れのことで、プログラムのメモリ管理とは関係がないものだとされている
  4. メモリリークは使い終わったメモリを返し忘れて、使えないメモリがたまっていく現象である
テクマスター
テクマスター 解答・解説

解答は 4 ですよ。

メモリリークは、使い終わったメモリを返し忘れて、使えないメモリがたまっていく現象ですね。たまり続けるといずれメモリが足りなくなります。図書館の本の借りっぱなしと同じイメージです。

選択肢1の「速くなる」、選択肢2の「画面に表示する機能」、選択肢3の「音漏れ」はどれも誤りですよ。

選択肢判定理由
1速くならず使えるメモリが減る
2表示する機能ではない
3音漏れではない
4返し忘れで使えないメモリがたまる

オリジナル問題2(GCでも起きる)

📝 オリジナル問題 2 GC言語でのリーク

GC(自動でメモリを回収するしくみ)とメモリリークについて、正しいものはどれか。

  1. GCのある言語でも、循環参照や参照の握りっぱなしによってメモリリークは起きることがある
  2. GCのある言語ではメモリリークは絶対に起きず、循環参照も自動で必ず解消されるものだとされる
  3. GCはメモリをわざと漏らすしくみのことで、リークを増やすために使われるものだとされている
  4. GCは画面の自動更新のしくみのことで、メモリの回収とは無関係なものだとされているものだ
テクマスター
テクマスター 解答・解説

解答は 1 ですよ。

GC(自動回収)があっても、循環参照や参照の握りっぱなしによってメモリリークは起きることがありますね。GCがあるから安全、と過信しないのがポイントです。

選択肢2の「絶対に起きない」、選択肢3の「わざと漏らすしくみ」、選択肢4の「画面の自動更新」はどれも誤りですよ。

選択肢判定理由
1循環参照などでGCでも起きる
2GCでも起きることがある
3わざと漏らすしくみではない
4画面の更新とは無関係

オリジナル問題3(検出と予防)

📝 オリジナル問題 3 検出ツールと予防策

メモリリークの検出・予防に関する次の記述のうち、正しいものはどれか。

  1. メモリリークは予防も検出もまったくできず、起きたら手の打ちようがないものだとされている
  2. メモリリークの予防にはRAIIやスマートポインタ、検出にはValgrindが使えるとされる
  3. メモリリークの検出はキーボードの掃除で行い、予防はモニタの拭き取りで行うものだとされる
  4. メモリリークの予防はメモリをいっさい使わないことだけで、ほかに方法はないものだとされている
テクマスター
テクマスター 解答・解説

解答は 2 ですよ。

予防には、スコープを抜けたら自動で返すRAIIや、持ち主を明示するスマートポインタが使えますね。検出にはValgrindやAddressSanitizerなどのツールがあります。

選択肢1の「手の打ちようがない」、選択肢3の「キーボードの掃除」、選択肢4の「メモリを一切使わない」はどれも誤りですよ。

選択肢判定理由
1予防も検出もできる
2予防はRAII等・検出はValgrind等
3物理的な掃除とは無関係
4メモリは使ってよい・仕組みで防ぐ

まとめ

押さえどころ

次に学ぶ


執筆: SikakuQuest編集部

勉強は、クエストになった。

資格の勉強を、冒険に変えるRPG学習アプリ

App Storeで見る