[Valgrind]動的割り当てを検出するメモリDAM(Dynamically Allocated Memory)

6258 ワード

目次
 、    
 、DAM  
 、  Valgrind        
 、       

一、インスタンスコード
配布コードパッケージChapter_07/pg_222/memprobs.c
1   #include 
2   #include 
3   
4   
5   
6   int main( void )
7   {
8       int *a = (int *) malloc( 3*sizeof(int) ); // malloc return not checked
9       int *b = (int *) malloc( 3*sizeof(int) ); // malloc return not checked
10  
11      for( int i = -1; i <= 3; ++i )
12          a[i] = i; // a bad write for i = -1 and 3.
13
14      free(a);
15      printf("%d
", a[1]); // a read from freed memory 16 free(a); // a double free on pointer a. 17 18 return 0; // program ends without freeing *b. 19 }

配布コードパッケージChapter_07/pg_222/Makefile
TARGET = memprobs
CC     = clang
CFLAGS = -g3 -Wall -Wextra -std=c99

all: $(TARGET)
.PHONY: clean

clean:
    $(RM) core $(TARGET)
run
$ ls
Makefile  memprobs.c

$ make memprobs
clang -g3 -Wall -Wextra -std=c99    memprobs.c   -o memprobs
memprobs.c:9:7: warning: unused variable 'b' [-Wunused-variable]
        int *b = (int *) malloc( 3*sizeof(int) ); // malloc return not checked
             ^
1 warning generated.

$ ./memprobs
*** Error in `./memprobs': double free or corruption (out): 0x0000000000cbd010 ***
Aborted (core dumped)

二、DAM問題
1、メモリ漏れ
  • は動的に割り当てられたメモリを解放せず、int *bが指す3つのintメモリは常に解放されなかった.
  • メモリの漏洩はメモリを消費し続け、プログラムが利用できるメモリがますます少なくなる.
  • メモリ漏洩のあるプログラムが終了すると、一部のオペレーティングシステムはこれらのメモリを回収し、一部のオペレーティングシステムはシステムが再起動するまで回収しない.

  • 2、malloc()への呼び出しに失敗した
  • 解決方法:malloc()の戻り値を検出することによって検出することができる.
  • 計算中のプログラムエラーは、値が大きすぎたり、負のDAM( malloc() )を要求したりして、呼び出しに失敗する可能性があります.
  • システムが本当にメモリがない場合、呼び出しに失敗します.

  • 3、アクセスエラー
  • は、DAMセグメント以外のアドレスへの読み取りおよび書き込み動作を実行する.
  • DAMセグメントを解放した後、DAM領域内のメモリに対して読み書き動作を実行する.

  • 4、繰り返し放出(double free)
  • 動的メモリの同じセグメントに対してfree()を2回呼び出す.

  • 三、Valgrindを使用してメモリ使用情報を表示する
  • $ valgrind --tool=memcheck --leak-check=full ./memprobs
  • $ valgrind --tool=memcheck --leak-check=full ./memprobs
    ==4126== Memcheck, a memory error detector
    ==4126== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
    ==4126== Using Valgrind-3.10.1 and LibVEX; rerun with -h for copyright info
    ==4126== Command: ./memprobs
    ==4126== 
    ==4126== Invalid write of size 4
    ==4126==    at 0x4005D4: main (memprobs.c:12)
    ==4126==  Address 0x51fc03c is 4 bytes before a block of size 12 alloc'd
    ==4126==    at 0x4C2AB80: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
    ==4126==    by 0x40059D: main (memprobs.c:8)
    ==4126== 
    ==4126== Invalid read of size 4
    ==4126==    at 0x4005FF: main (memprobs.c:15)
    ==4126==  Address 0x51fc044 is 4 bytes inside a block of size 12 free'd
    ==4126==    at 0x4C2BDEC: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
    ==4126==    by 0x4005F2: main (memprobs.c:14)
    ==4126== 
    1
    ==4126== Invalid free() / delete / delete[] / realloc()
    ==4126==    at 0x4C2BDEC: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
    ==4126==    by 0x400614: main (memprobs.c:16)
    ==4126==  Address 0x51fc040 is 0 bytes inside a block of size 12 free'd
    ==4126==    at 0x4C2BDEC: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
    ==4126==    by 0x4005F2: main (memprobs.c:14)
    ==4126== 
    ==4126== 
    ==4126== HEAP SUMMARY:
    ==4126==     in use at exit: 12 bytes in 1 blocks
    ==4126==   total heap usage: 2 allocs, 2 frees, 24 bytes allocated
    ==4126== 
    ==4126== 12 bytes in 1 blocks are definitely lost in loss record 1 of 1
    ==4126==    at 0x4C2AB80: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
    ==4126==    by 0x4005B0: main (memprobs.c:9)
    ==4126== 
    ==4126== LEAK SUMMARY:
    ==4126==    definitely lost: 12 bytes in 1 blocks
    ==4126==    indirectly lost: 0 bytes in 0 blocks
    ==4126==      possibly lost: 0 bytes in 0 blocks
    ==4126==    still reachable: 0 bytes in 0 blocks
    ==4126==         suppressed: 0 bytes in 0 blocks
    ==4126== 
    ==4126== For counts of detected and suppressed errors, rerun with: -v
    ==4126== ERROR SUMMARY: 5 errors from 4 contexts (suppressed: 0 from 0)
    

    エラー情報解析Line:12最初のループは、a[-1]の境界配列にアクセスします.
  • は、==4126== Invalid write of size 4 at 0x4005D4: main (memprobs.c:12) Address 0x51fc03c is 4 bytes before a block of size 12 alloc'd
  • として記述する.
  • あなたがアクセスした場所は、割り当てられた12バイトのメモリの前に
  • あります.
  • の核心語はInvalid readbeforealloc'dである.
  • Line:15のアクセスエラー、解放されたDAMセグメントへのアクセス
  • は、Invalid read of size 4 at 0x4005FF: main (memprobs.c:15) Address 0x51fc044 is 4 bytes inside a block of size 12 free'd
  • として記述する.
  • 間違いなく12バイト割り当てられたメモリブロックにアクセスしましたが、このメモリブロックはfree'd`
  • を解放しました.
  • の核心語はInvalid readinsidefree'dである.
  • Line: 16のdouble free()
  • は、Invalid free() / delete / delete[] / realloc() ... Address 0x51fc040 is 0 bytes inside a block of size 12 free'd
  • として記述する.
  • ここには無効な解放があります.なぜなら、解放された領域を解放し、
  • を繰り返し解放したからです.
  • コアワードはInvalid free()insidefree'd
  • Line:9の解放されていないint *b
  • は、12 bytes in 1 blocks are definitely lost in loss record 1 of 1
  • として記述する.
  • 特定のメモリ漏洩、12 はちょうど3 int
  • です.
  • コアワードはdefinitely lost
  • です.
    四、ツールのインストールと参考
    Valgrind
  • 取付sudo apt-get install valgrind
  • Quick Start

  • http://valgrind.org/docs/manual/quick-start.html
  • Memcheck:すべてのタイプのエラー情報解釈
  • 4.2. Explanation of error messages from Memcheck http://valgrind.org/docs/manual/mc-manual.html#mc-manual.errormsgs
  • 公式manual
  • http://valgrind.org/docs/manual/manual.html
  • ValgrindアプリケーションLinuxプログラムのメモリの問題を発見
  • https://www.ibm.com/developerworks/cn/linux/l-cn-valgrind/
    書籍と関連ノートの使用
    [書籍]『ソフトウェアデバッグの芸術』(『The Art of Debugging with GDB,DDD,and Eclipse』)https://www.jianshu.com/p/0805ba683126