Valgrind
ツイートValgrindとはメモリを主眼に置いた、メモリでバッグやメモリリークの検出、プロファイリング等を行うツールです。
C言語は特にメモリ周辺のバグが多く現在でも多くのソフトウェアで日々バグが発見、修正されています。
こういった問題はprintデバッグでは発見しづらく、これを手助けしてくれるツールですので積極的に利用するのがよいでしょう。
Valgrind
インストール
まずはインストールから。
gcc等の環境はインストールされているはずなので省略します。
// Debian系 $ apt-get install valgrind // Red Hat系 $ yum install valgrind //or $ dnf install valgrind
機能
Valgrind(tools)等によると様々な機能があるようです。シグナルはint型の整数で定義されています。有名なシグナルをいくつか紹介しましょう。
Memcheck | メモリエラー検出ツール。特にC、C++に向いています |
Cachegrind | キャッシュプロファイラ。GUIはKCacheGrind。 |
Callgrind | コールグラフ、つまり関数呼び出しの可視化を行う |
Helgrind | スレッドエラーの検出。マルチスレッドの競合状態を検出してくれる |
DRD | スレッドエラーの検出。Helgrindとはアプローチが異なり、検出する問題も違うらしい |
Massif | ヒーププロファイラ。メモリ使用量を抑えたりするのに使えるでしょう |
DHAT | 動的ヒープ解析 |
SGCheck | 実験段階とのこと。Memcheckと似ているがこちらはスタックやグローバル領域向け |
BBV | 実験段階とのこと。基本ブロックベクター生成ツールらしい... |
Lackey | ツールのサンプルコード |
Nulgrind | 何もしません。ベンチマークやサンプル用 |
使い方
まずは定番なHello Worldから。
#include <stdio.h> int main(void) { printf("Hello World\n"); return 0; }
コンパイル時には'-g'オプションを忘れずに。
$ gcc -g -o hello hello.c $ ./hello Hello World
Valgrindの使用方法は、valgrindコマンドに実行コマンドを渡します
$ valgrind ./hello ==30444== Memcheck, a memory error detector ==30444== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al. ==30444== Using Valgrind-3.11.0 and LibVEX; rerun with -h for copyright info ==30444== Command: ./hello ==30444== Hello World ==30444== ==30444== HEAP SUMMARY: ==30444== in use at exit: 0 bytes in 0 blocks ==30444== total heap usage: 1 allocs, 1 frees, 1,024 bytes allocated ==30444== ==30444== All heap blocks were freed -- no leaks are possible ==30444== ==30444== For counts of detected and suppressed errors, rerun with: -v ==30444== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
実行時には使用したい機能毎にオプションを指定できます。
通常valgrindを使う場合はメモリリークチェックが主になります。
メモリリークを検出するには'--leak-check'オプションを利用します。
このコードはよくあるアクセスしてはいけない領域への書き込みです
#include <stdio.h> #include <stdlib.h> int main(void) { int *p; p = malloc(4); p[4] = 0; //NG return 0; }
見事に検出されています。'-g'オプションをつけているので、行数まで表示されています。
$ valgrind --leak-check=full ./hoge ==32456== Memcheck, a memory error detector ==32456== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al. ==32456== Using Valgrind-3.11.0 and LibVEX; rerun with -h for copyright info ==32456== Command: ./hoge ==32456== ==32456== Invalid write of size 4 ==32456== at 0x400544: main (hoge.c:9) ==32456== Address 0x5203050 is 12 bytes after a block of size 4 alloc'd ==32456== at 0x4C2DB8F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) ==32456== by 0x400537: main (hoge.c:8) ==32456== ==32456== ==32456== HEAP SUMMARY: ==32456== in use at exit: 4 bytes in 1 blocks ==32456== total heap usage: 1 allocs, 0 frees, 4 bytes allocated ==32456== ==32456== 4 bytes in 1 blocks are definitely lost in loss record 1 of 1 ==32456== at 0x4C2DB8F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) ==32456== by 0x400537: main (hoge.c:8) ==32456== ==32456== LEAK SUMMARY: ==32456== definitely lost: 4 bytes in 1 blocks ==32456== indirectly lost: 0 bytes in 0 blocks ==32456== possibly lost: 0 bytes in 0 blocks ==32456== still reachable: 0 bytes in 0 blocks ==32456== suppressed: 0 bytes in 0 blocks ==32456== ==32456== For counts of detected and suppressed errors, rerun with: -v ==32456== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0)
他にはこのような場合も検出できます。
フリーを行っていない
int func(void) { p = malloc(4); // pをfreeしていない return 0; }
ダブルフリー(同じポインタを2回feeする)
p = malloc(4); free(p); free(p); //pはfree済み
freeした領域へのアクセス
p = malloc(4); free(p); p[0] = 0; //free済み領域への書き込み
初期化していない領域の参照
int x; printf("%d\n", x); //xは未初期化
メモリリークチェック以外にも、他の機能もありますの簡単に使い方を見ましょう。
ヒーププロファイラ
$ valgrind --tool=massif ./hoge
コールトレース
$ valgrind --tool=callgrind ./hoge
まとめ
C言語は他の言語に比べて低級なために細かな所までアクセスするが為にバグも多く、特にメモリ周りはその主な原因となっています。
機械的な物なのですから、人間が根性で頑張るのではなくデバッグもプログラムで行うのが自然でしょう。
Valgrindはこういった要求に応えるためのツールです。楽をして開発を行うためにも選択肢の1つに入れておきましょう
リーダブルコード ―より良いコードを書くためのシンプルで実践的なテクニック (Theory in practice) Dustin Boswell,Trevor Foucher,須藤 功平,角 征典 オライリージャパン 売り上げランキング : 1022 Amazonで詳しく見る by AZlink |
テスト駆動開発による組み込みプログラミング ―C言語とオブジェクト指向で学ぶアジャイルな設計 James W. Grenning,蛸島 昭之,笹井 崇司 オライリージャパン 売り上げランキング : 34157 Amazonで詳しく見る by AZlink |