「領域外書き込み」とは、確保した領域外に値を書き込むことを言います。いわゆるメモリ破壊ですね。領域外(別の変数)に書き込むと、別変数を読み出した場合、変数値が破壊され、不可解な現象が起こる原因となります(バグの現象に規則性がないため、単純なバグながら、検出するのは非常に大変です)。リスト3で、考えてみましょう。
#include<stdlib.h> int main(){ char *str; str = (char*)malloc(5); str[5] = 'b'; free(str); return 0; }
リスト3は、char型で5バイト分をmalloc関数を使って確保しました。つまり、変数strは、0〜4番地にアクセスできます。しかし、5行目では、strが範囲外の5番地に「b」を書き込んでいます。典型的な領域外アクセスですね。valgrindを実行すると、図3のようなエラーメッセージが出ます。
3行目に「Invalid write of size 1」と出ており、「1バイト誤って書き込んでいます」の意味です。例えば、5行目を「str[4] = 'b';」に変更すると、Valgrindのエラーメッセージはなくなります。
リスト2、3のように短い例題では、メモリのアクセス例外はすぐに発見できますが、扱う範囲が増えると、分かりにくくなります。Valgrindをデバッグ時に使用し、見つけにくいバグを機械的に広範囲で検出すると、時間と労力の節約になります。
今回の内容を以下にまとめます。
エンジニアは、決まった時間内に最大限の成果物を出力することが重要です。そのためには、単純作業は極力減らすべきでしょう。Valgrindは、プログラマーが見落としやすいメモリ関連のバグを瞬時に検出するツールで、デバッグ時に有効です。この類のツールは有償、無償問わず数多く出回っていますので、調べてみるといいでしょう。
[1]「モダンC言語プログラミング」(花井志生、2013、KADOKAWA/アスキーメディアワークス社)
[2]「デバッグの理論と実践 なぜプログラムはうまく動かないのか」(Andreas Zeller他、2012、オライリージャパン)
東海大学 大学院 組込み技術研究科 非常勤講師(工学博士)
Copyright © ITmedia, Inc. All Rights Reserved.