Ubuntuでメモリリークを検出・修正する方法:ステップバイステップガイド
Ubuntuでメモリリークが発生する原因はいくつかありますが、幸いにも、発生した際には比較的わかりやすいのが特徴です。最大の原因はバグを含むコードであることが多く、プログラマーが不要になったメモリを適切に解放する処理を確認する機会がなかった場合に起こりがちです。不安定なパッケージをインストールしたり、ソースコードから自分でビルドしたりしている場合も、メモリリークに悩まされる可能性があります。十分な物理RAMを搭載しているはずなのに、アプリケーションが「メモリ不足」のエラーを出し始めたら、メモリリークの兆候と考えられます。
メモリリークが心配な場合は、ターミナルで free コマンドを繰り返し実行してみてください。RAM使用量が急激に増加していく様子が見えたら、すでにメモリリークが発生しています。また、ターミナルや仮想コンソールしか開いていない状態で「bash: Not enough Memory(メモリが足りません)」のようなエラーが表示された場合は、ほぼ間違いなくメモリリークが起きています。より分かりにくいリークもありますが、Ubuntuおよびその派生ディストリビューションには、こうした問題を検出するためのツールやパッケージが用意されています。
Ubuntuでのメモリリークの検出方法
メモリリークの検出に使われるツールは主にCLI(コマンドライン)ベースのため、どのバージョンのUbuntuでも同じように動作します。通常のUbuntuのターミナルでも、Ubuntu Serverの仮想コンソールでも、Lubuntuのlxterm、KubuntuのKonsole、XubuntuのXfceターミナルでも問題なく利用できます。まずは sudo -s を実行し、パスワードを入力してrootシェルを取得するところから始めましょう。
正しく実行できればrootシェルが取得できますが、リークがすでに深刻化している場合はメモリエラーが出ることもあります。rootシェルに入れたら、次のコマンドを実行してください。
echo 3 > /proc/sys/vm/drop_caches
Enterキーを押してから exit と入力します。その後、free または free -m を再度実行し、メモリが解放されたかどうかを確認しましょう。
カーネルにキャッシュを強制的に破棄させることに意味がないと主張するプログラマーもいます。追加の物理メモリが必要になった時点で、キャッシュは自動的にフラッシュされ再利用されるはずだからです。確かにキャッシュの強制フラッシュはシステムパフォーマンスを低下させますが、これはあくまでテスト目的だと考えてください。システムを再起動すれば、Linuxカーネルは再び元通りのメモリキャッシュを構築します。
sync; sudo echo 3 > /proc/sys/vm/drop_caches のような行をcronで定期的に実行するスクリプトに追加することを勧める人もいますが、これはメモリキャッシュの本来の目的を損なう行為です。空きメモリとは単なる「未使用のRAM」であり、つまりデータはより低速な電気機械式ストレージやNANDフラッシュストレージから読み込まなければなりません。どんなに高速なデバイスでもRAMほど速くはないため、メモリリークは修正すべきですが、最適化されたキャッシュ設定に一度手を加えたら、それ以上いじらないことが重要です。
マシンの使用中に定期的にメモリリークが発生しているものの、特定の原因を絞り込めない場合でも、CLIアクセスがあるなら top コマンドを実行してみてください。実行中のプロセスの一覧が表示されます。
top について通常とは異なるエラーが表示される場合は、busybox top を代わりに実行すると、さらにシンプルなバージョンのプログラムにアクセスできます。一覧が表示されたら、%MEM などの列を見て、どのアプリケーションに最も多くのメモリが割り当てられているかを確認します。PIDを記録して kill コマンドで該当プロセスを終了させることもできますが、これは単にアプリケーションを強制終了するだけなので、メモリが解放されるとは限りません。それでも試してみる価値はあります。
大量のメモリを使用しているアプリケーションが見つかったら、q キーを押して top を終了し、先ほどの画面で確認したPID番号を使って kill #### を実行します。ただし、システムプロセスや未保存の作業があるプロセスをこの方法で終了させてはいけません。GUI環境では、Ctrl+Alt+Delで呼び出せるタスク管理ツールから同様の操作を行うことも可能です。
特定のプログラムでこの現象が繰り返し起こることが判明したら、今後の発生を防ぐためにそのプログラムの設定を見直しましょう。もちろん、個々のプログラムごとに対処法は異なり、それは単なるメモリリーク検出の範囲を超えた作業になります。
開発者向け:コードレベルでのメモリリーク対策
アプリケーションのトラブルシューティングだけでなく、実際にコードを書いている場合には、他にも利用できる手段があります。Ubuntuとその派生ディストリビューションでは、membarrier、memusage、memusagestat といったC言語ルーチンをプログラミングに活用できます。
man membarrier、man memusage、man memusagestat を実行すれば、これらの重要なルーチンに関するLinux Programmer's Manualのページを参照できます。新しいバージョンのUbuntuがリリースされてライブラリにアップグレードがあった場合も、変更点は必ずここに記載されます。
グラフィカルな情報が必要な場合は、memusagestat にはメモリ使用状況をPNGファイルとして保存するオプションもあります。この機能はユーティリティの作者にとっても魅力的で、定期的にメモリリークをチェックするアプリケーションを作成する際に活用できます。
また、memprof をインストールするのもおすすめです。これはメモリ使用量をプロファイリングし、メモリリークの発見を支援するツールです。作成中のプログラム内の各関数がどれだけのメモリを割り当てているかに関するプロファイルを生成します。さらに、既存のメモリをスキャンして、割り当て済みだが有効な参照がなくなったブロックを検出することもできます。これは標準Cライブラリのメモリ割り当て機能を上書きするためにライブラリをプリロードすることで実現されています。
memprof を使用する場合は、コードを公開する前に、コード冒頭の include memprof の行を必ず削除してください。リークがないことを確認するために使うものですが、コードをパッケージ化してリポジトリで公開する際に依存関係になってしまうのは望ましくありません。
まとめ
Ubuntuでのメモリリークは、free コマンドによる監視、top コマンドによるプロセス分析、そして開発者向けの memusage や memprof などのツールを組み合わせることで効果的に検出・対処できます。定期的な監視習慣をつければ、問題が深刻化する前に発見できるでしょう。
著者について

Kevin Arrows(ケビン・アローズ)
Kevin Arrowsは、10年以上の業界経験を持つテクノロジースペシャリストです。Microsoft Certified Technology Specialist(MCTS)認定資格を保有し、最新の技術動向を追いかけることに深い情熱を持っています。ソフトウェア開発、サイバーセキュリティ、クラウドコンピューティングなど幅広い技術トピックについて執筆しており、複雑な技術的概念を明確かつ簡潔に説明する能力で業界内外から高い評価を得ています。
-
「sudo: no tty present and no askpass program specified」エラーの対処法
SSH接続中にsudoコマンドを実行した際に表示される「sudo: no tty present and no askpass program specified」というエラーメッセージは、実際の原因を的確に伝えてくれないことで知られています。このメッセージが表示されていても、実は有効なTTYを利用しているケースがほとんどです。また、普段はSSH経由でもsudoパスワードを問題なく入力できているという方も多いでしょう。つまり、このエラーの多くは構文ミスに起因しているのですが、エラーメッセージ自体はその事実に直接触れてはいません。この問題はSSHそのものに関連しているため、Linux、FreeB
-
Ubuntuのログイン画面を復元する方法:削除したパッケージを数コマンドで修復
大量のパッケージを削除していた際に、うっかりlightdmなどの重要なパッケージまで削除してしまったことはありませんか?このパッケージはグラフィカルデスクトップへのログインを可能にするもので、多くの場合、起動時に自動的にデスクトップへ誘導してくれます。これを削除したまま再起動すると、真っ暗な画面が表示されるだけになってしまうでしょう。 しかし心配はいりません。最小限の操作でログイン画面を修復できる可能性が高いのです。作業を始める前に、可能であればイーサネットケーブルを接続し、ノートパソコンであれば充電器をつないでおきましょう。パッケージ管理を行う際には、これが最も安全な選択となります。 ubu