.net column
.NET開発者のためのブログメディア

メモリリークとは何?発生する原因と発生を防ぐ方法について解説!

 
メモリリークとは何?発生する原因と発生を防ぐ方法について解説!
基本情報技術者試験の試験対策はこちら>>
PG
メモリリークが発生したら大変そうですね。ガベージコレクションが搭載されているからといって、メモリに関しての知識はおろそかにできないですよね。
PL
メモリはアプリケーション開発で重要な部分です。メモリ管理の知識がなくては良いアプリケーションはできないといっていいでしょう。

メモリリークとは何か


開発したプログラムを動作させる場合、作業領域であるメモリが必要になります。「メモリリーク(memory leak)」とは、プログラムによってメモリが枯渇してしまい、プログラムが実行できなくなる現象のことです。

メモリリークはプログラミングにおけるバグの1つとされており、実行中のプログラムがメモリ領域の解放を行わないまま放置してしまうことなどが原因で発生します。本記事ではメモリリークについてご紹介していきます。

メモリリークの4つの種類


メモリリークとひとことで言っても、メモリリークにはその発生原因によって4つの種類にわけることができます。具体的には、「LEAK_RETURN」「LEAK_ASSIGN」「LEAK_SCOPE」「LEAK_FREE」の4種類です。

ここではメモリリークの4つの種類についてそれぞれご紹介していきますので、ぜひ参考にしてみてはいかがでしょうか。

1:LEAK_RETURN

「LEAK_RETURN」とは、戻り値が無視されたことが原因で発生するメモリリークです。メモリリークはメモリブロックを指すポインタが何らかの原因によって失われることにより、動的に割り当てられたメモリブロックが解放できずに発生するエラーです。

LEAK_RETURNでは関数がメモリブロックを指すポインタを呼び出し元へ返した際に、ポインタが呼び出し元で無視されることによって発生します。

2:LEAK_ASSIGN

「LEAK_ASSIGN」とは、アドレスを上書きしたことが原因で発生するメモリリークです。LEAK_ASSIGNはポインタの再設定により、動的に振り分けられたメモリブロックが解放できなくなった際に発生します。

特に動的に割り当てられたブロックを指すポインタが上書きされてしまうと、LEAK_ASSIGNが発生してしまいます。

3:LEAK_SCOPE

「LEAK_SCOPE」とは、自動変数を失うことによって発生するメモリリークです。LEAK_SCOPEは特定のメモリブロックを指すポインタが関数を保持している場合に、ポインタをブローバル変数に保存せずに関数が終了することで自動変数が喪失した場合などに発生します。

また、ポインタを戻り値として戻さないまま関数が終了した場合にも発生します。

4:LEAK_FREE

「LEAK_FREE」とは、メモリを開放した際に発生するメモリリークです。メモリを開放する際に、解放したメモリブロックの中に別のメモリブロックを指すポインタが含まれている場合、LEAK_FREEが発生します。

メモリリークが発生してしまう原因とは


以下、メモリリークが発生する主な原因です。

1. 静的メンバーを利用している
staticキーワードがある場合は静的メンバーです。ガベージコレクションの対象となるのは、ヒープ領域にあるオブジェクトです。静的メンバーは対象外のため、静的領域に残り続けることになります。

2. Disposeメソッドを呼び出していない

3. 不完全なDisposeメソッドを利用している

4. WindowsフォームでBindingSourceコンポーネントの使い方を間違えている

メモリリーク発生頻度が少ない言語について


メモリリークの発生を防ぐ機能としては、.NET Frameworkなどに搭載されているガベージコレクションがあります。ガベージコレクションは高度なプログラミング言語に搭載されている機能で、関数型言語の多くはガベージコレクションを組み込んでいます。

また、Rubyなどの動的言語も、Javaのようなオブジェクト指向型言語もガベージコレクションを備えているケースが多いため、メモリリークの発生頻度は少ないと言えるでしょう。

ただし、すべての領域がガベージコレクションの対象というわけではないため、ガベージコレクションの対象外の領域ではメモリリークが発生することがあります。そのため、開発者にはメモリに関する知識が必要になります。

メモリリークの発生を防ぐ方法


開発者自身の手でメモリリークの発生を防ぐには、たとえば以下のような方法があります。

1. なるべくusing ステートメントを活用して、ステートメントが抜けたら自動でDisposeメソッドが発動されるようにする
2. オブジェクトがイベントを生成する必要がなくなったら、そのオブジェクトに対して、NullやNothingを設定する
3. 不要なイベントは呼び出さないようにする
4. オブジェクトの利用者側で破棄するのではなく、オブジェクトを作成した側で破棄するようにする

特にC言語などはガベージコレクションが搭載されていないため、開発者はメモリを開放するようにコーディングを行う必要があります。

ガベージコレクションについて

ガベージコレクションとは、不要なメモリを自動で解放する機能です。ガベージコレクションの働きによって、.NET Frameworkなどの高レベルの言語ではメモリリークは発生しにくいといわれています。

しかし、ガベージコレクションの対象外の領域も存在するため、その領域でメモリが自動的に解放されずにプログラムが実行されるたびにメモリ領域を占有すれば、メモリリークが発生することになります。

IDisposable・usingの使い方

IDisposableインターフェースでは「Dispose()」というメソッド内でリソースの解放を行います。たとえばリソース開放が必要なクラスを使用する場合、使い終わりのタイミングで「Dispose()」を呼びましょう。

また、usingは「Dispose()」を自動的に呼び出す構文です。usingのスコープから離れたタイミングや例外が発生した場合、自動的にDispose() を呼び出してくれます。

メモリリークを調査するツールとは?


メモリリークの調査にはフレームワークの「Valgrind」などが利用できます。Valgrindはメモリリークや不正なメモリアクセスを検出することができるため、Valgrindを活用することで開発者がデバッグ時に気付けないミスを発見することができます。

PG
C#は、ガベージコレクションが搭載されていて良かったです。なければ解放漏れを起こして絶対にメモリリークを発生させてしまいそうです。
PL
C言語など、ガベージコレクションが搭載されていない言語で開発する場合、メモリの解放は開発者自身に委ねられます。.NET Frameworkではガベージコレクションが搭載されていますが、メモリの解放に関しては自らが意識してコーディングすることが必要ですよ。

メモリリークの発生を未然に防ごう!


メモリリークが基幹システムなどのサーバーで動作するプログラムで発生した場合、システム全体に影響を及ぼしてしまう事になります。そのため、開発者は仕様どおりに開発するのはもちろん、メモリリークについてもしっかりと意識し、発生を防ぐ必要があります。


.NET分野でのキャリアアップをお考えの方は、現在募集中の求人情報をご覧ください。

また、直接のエントリーも受け付けております。

エントリー(応募フォーム)

Search

Popular

reccomended

Categories

Tags