Valgrind
提供: セキュリティ
スポンサーリンク
Valgrind とは、動的プログラム解析のツールです。CやC++のメモリリークを検出できます。
読み方
- Valgrind
- ヴァルグリンド ばるぐりんど
目次
概要
インストール
FreeBSDにインストールする場合
ports コレクションからインストールする場合
cd /usr/ports/devel/valgrind sudo make install clean
pkgコマンドでインストールする場合
sudo pkg install valgrind
portmasterコマンドでインストールする場合
sudo portmaster -y -d /usr/ports/devel/valgrind
portinstallコマンドでインストールする場合
sudo portinstall /usr/ports/devel/valgrind
Ubuntuにインストール
sudo apt install valgrind
使い方
valgrind a.out arg1 arg2 valgrind --leak-check=full a.out arg1 arg2
valgrind --leak-check=full \ --show-leak-kinds=all \ --track-origins=yes \ --verbose \ --log-file=valgrind-out.txt \ ./command
malloc()の解放漏れの検出
mallocの解放漏れを検出する例です。
mallo.c
main()でmallocを呼び出し、メモリを動的に確保します。確保したメモリをfreeせずに終了します。
#include <stdlib.h> int main(int argc, char const* argv[]) { char *p = (char *) malloc (sizeof(char) * 1234); *p = '\0'; return 0; }
コンパイル
デバッグ情報を含めておくため、 -g オプションを付けます。
gcc -g malloc.c
valgrindの実行
通常のチェックでは、何も見つかりませんでした。
valgrind a.out ==75419== Memcheck, a memory error detector ==75419== Copyright (C) 2002-2012, and GNU GPL'd, by Julian Seward et al. ==75419== Using Valgrind-3.8.1 and LibVEX; rerun with -h for copyright info ==75419== Command: a.out ==75419== ==75419== ==75419== HEAP SUMMARY: ==75419== in use at exit: 1,234 bytes in 1 blocks ==75419== total heap usage: 1 allocs, 0 frees, 1,234 bytes allocated ==75419== ==75419== LEAK SUMMARY: ==75419== definitely lost: 1,234 bytes in 1 blocks ==75419== indirectly lost: 0 bytes in 0 blocks ==75419== possibly lost: 0 bytes in 0 blocks ==75419== still reachable: 0 bytes in 0 blocks ==75419== suppressed: 0 bytes in 0 blocks ==75419== Rerun with --leak-check=full to see details of leaked memory ==75419== ==75419== For counts of detected and suppressed errors, rerun with: -v ==75419== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
--leack-checkは、クライアントプログラムが終了したときに、メモリリークの検索を有効にするオプションです。 4行目のmalloc()の解放漏れが検出されました。
% valgrind --leak-check=full a.out ==75446== Memcheck, a memory error detector ==75446== Copyright (C) 2002-2012, and GNU GPL'd, by Julian Seward et al. ==75446== Using Valgrind-3.8.1 and LibVEX; rerun with -h for copyright info ==75446== Command: a.out ==75446== ==75446== ==75446== HEAP SUMMARY: ==75446== in use at exit: 1,234 bytes in 1 blocks ==75446== total heap usage: 1 allocs, 0 frees, 1,234 bytes allocated ==75446== ==75446== 1,234 bytes in 1 blocks are definitely lost in loss record 1 of 1 ==75446== at 0x36308: malloc (in /usr/local/lib/valgrind/vgpreload_memcheck-x86-freebsd.so) ==75446== by 0x80484BC: main (malloc.c:4) ==75446== ==75446== LEAK SUMMARY: ==75446== definitely lost: 1,234 bytes in 1 blocks ==75446== indirectly lost: 0 bytes in 0 blocks ==75446== possibly lost: 0 bytes in 0 blocks ==75446== still reachable: 0 bytes in 0 blocks ==75446== suppressed: 0 bytes in 0 blocks ==75446== ==75446== For counts of detected and suppressed errors, rerun with: -v ==75446== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
ソースコードのパスを指定できます。エラーメッセージで、コードのパスが正しく表示されます。
% valgrind --leak-check=full --fullpath-after=$PWD/a.out ==75461== Memcheck, a memory error detector ==75461== Copyright (C) 2002-2012, and GNU GPL'd, by Julian Seward et al. ==75461== Using Valgrind-3.8.1 and LibVEX; rerun with -h for copyright info ==75461== Command: a.out ==75461== ==75461== ==75461== HEAP SUMMARY: ==75461== in use at exit: 1,234 bytes in 1 blocks ==75461== total heap usage: 1 allocs, 0 frees, 1,234 bytes allocated ==75461== ==75461== 1,234 bytes in 1 blocks are definitely lost in loss record 1 of 1 ==75461== at 0x36308: malloc (in /usr/local/lib/valgrind/vgpreload_memcheck-x86-freebsd.so) ==75461== by 0x80484BC: main (/home/foo/sourcecode_scan/c/malloc.c:4) ==75461== ==75461== LEAK SUMMARY: ==75461== definitely lost: 1,234 bytes in 1 blocks ==75461== indirectly lost: 0 bytes in 0 blocks ==75461== possibly lost: 0 bytes in 0 blocks ==75461== still reachable: 0 bytes in 0 blocks ==75461== suppressed: 0 bytes in 0 blocks ==75461== ==75461== For counts of detected and suppressed errors, rerun with: -v ==75461== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
バッファオーバーラン
buffer_over_malloc.c
#include <stdlib.h> int main(int argc, char const* argv[]) { int *a = (int *) malloc (sizeof(int) * 2); a[2] = 0; free(a); return 0; }
コンパイル
gcc -g buffer_over_malloc.c
Valgrindの実行
% valgrind --leak-check=full a.out ==75526== Memcheck, a memory error detector ==75526== Copyright (C) 2002-2012, and GNU GPL'd, by Julian Seward et al. ==75526== Using Valgrind-3.8.1 and LibVEX; rerun with -h for copyright info ==75526== Command: a.out ==75526== ==75526== Invalid write of size 4 ==75526== at 0x80484F6: main (buffer_over_malloc.c:5) ==75526== Address 0x180038 is 0 bytes after a block of size 8 alloc'd ==75526== at 0x36308: malloc (in /usr/local/lib/valgrind/vgpreload_memcheck-x86-freebsd.so) ==75526== by 0x80484EC: main (buffer_over_malloc.c:4) ==UNIQ93d4d711ba7a66f8-h-27--QINU75526== ==UNIQ93d4d711ba7a66f8-h-28--QINU75526== ==75526== HEAP SUMMARY: ==75526== in use at exit: 0 bytes in 0 blocks ==75526== total heap usage: 1 allocs, 1 frees, 8 bytes allocated ==UNIQ93d4d711ba7a66f8-h-29--QINU75526== ==75526== All heap blocks were freed -- no leaks are possible ==UNIQ93d4d711ba7a66f8-h-30--QINU75526== ==75526== For counts of detected and suppressed errors, rerun with: -v ==75526== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
ヒーププロファイラ
% gcc -g buffer_over.c % valgrind --tool=massif a.out ==75538== Massif, a heap profiler ==75538== Copyright (C) 2003-2012, and GNU GPL'd, by Nicholas Nethercote ==75538== Using Valgrind-3.8.1 and LibVEX; rerun with -h for copyright info ==75538== Command: a.out ==75538== ==75538== % cat massif.out.75538 desc: (none) cmd: a.out time_unit: i #----------- snapshot=0 #----------- time=0 mem_heap_B=0 mem_heap_extra_B=0 mem_stacks_B=0 heap_tree=empty #----------- snapshot=1 #----------- time=319352 mem_heap_B=1234 mem_heap_extra_B=22 mem_stacks_B=0 heap_tree=empty
valgrind コマンドで massif.out.PID (PIDはプロセスIDに読み替えてください)というファイルが作成されます。 ms_printコマンドでMassifを表示できます。 メモリの使用量の推移などがわかります。
% gcc -g malloc_leak_loop.c % valgrind --tool=massif a.out % ms_print massif.out.75651 -------------------------------------------------------------------------------- Command: a.out Massif arguments: (none) ms_print arguments: massif.out.75651 -------------------------------------------------------------------------------- GB 1.451^ : | @ | @ | @@ | @@ | @@ | :@@ | :@@ | :@@@ | :@@@ | @@@@ | :@@@@ | @@@@@ | @@@@@ | @@@@@@ | @@@@@@ | :@@@@@@ | :@@@@@@ | @@@@@@@ | @@@@@@@@ 0 +----------------------------------------------------------------------->ki 0 348.8 Number of snapshots: 93 Detailed snapshots: [6, 11, 24, 29, 34, 39, 44, 49, 59, 69, 79, 89] -------------------------------------------------------------------------------- n time(i) total(B) useful-heap(B) extra-heap(B) stacks(B) -------------------------------------------------------------------------------- 0 0 0 0 0 0 1 319,363 2,097,160 2,097,152 8 0 2 320,179 35,651,720 35,651,584 136 0 3 320,587 52,429,000 52,428,800 200 0 4 320,995 69,206,280 69,206,016 264 0 5 321,403 85,983,560 85,983,232 328 0 6 321,811 102,760,840 102,760,448 392 0 100.00% (102,760,448B) (heap allocation functions) malloc/new/new[], --alloc-fns, etc. ->100.00% (102,760,448B) 0x80484B0: leak (malloc_leak_loop.c:3) ->100.00% (102,760,448B) 0x80484EB: main (malloc_leak_loop.c:12) -------------------------------------------------------------------------------- n time(i) total(B) useful-heap(B) extra-heap(B) stacks(B) -------------------------------------------------------------------------------- 7 322,219 119,538,120 119,537,664 456 0 8 322,627 136,315,400 136,314,880 520 0 9 323,035 153,092,680 153,092,096 584 0 10 323,443 169,869,960 169,869,312 648 0 11 323,851 186,647,240 186,646,528 712 0 100.00% (186,646,528B) (heap allocation functions) malloc/new/new[], --alloc-fns, etc. ->100.00% (186,646,528B) 0x80484B0: leak (malloc_leak_loop.c:3) ->100.00% (186,646,528B) 0x80484EB: main (malloc_leak_loop.c:12) -------------------------------------------------------------------------------- n time(i) total(B) useful-heap(B) extra-heap(B) stacks(B) -------------------------------------------------------------------------------- 12 324,259 203,424,520 203,423,744 776 0 13 324,667 220,201,800 220,200,960 840 0 14 325,075 236,979,080 236,978,176 904 0 15 325,483 253,756,360 253,755,392 968 0 16 325,891 270,533,640 270,532,608 1,032 0 17 326,299 287,310,920 287,309,824 1,096 0 18 326,707 304,088,200 304,087,040 1,160 0 省略
関連項目
ツイート
スポンサーリンク