Valgrind

提供: セキュリティ
2015年9月22日 (火) 16:20時点におけるDaemon (トーク | 投稿記録)による版

移動: 案内検索
スポンサーリンク

Valgrind とは、動的プログラム解析のツールです。CC++メモリリークを検出できます。

読み方

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

使い方

valgrind a.out arg1 arg2
valgrind --leak-check=full a.out arg1 arg2

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)
==UNIQ8075abdf6a16951d-h-26--QINU75526==
==UNIQ8075abdf6a16951d-h-27--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
==UNIQ8075abdf6a16951d-h-28--QINU75526==
==75526== All heap blocks were freed -- no leaks are possible
==UNIQ8075abdf6a16951d-h-29--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
 
省略

関連項目




スポンサーリンク