본문 바로가기
프로그램 (PHP,Python)

Valgrind 디버깅과 프로파일링

by 날으는물고기 2009. 7. 4.

Valgrind 디버깅과 프로파일링

1 개요

1.1 Valgrind란?

Valgrind는 Linux-x86 용 실행 파일의 디버깅과 프로파일링을 위한 오픈 소스 툴이다. Valgrind는 Memcheck이나 Addrcheck 툴을 사용하여 실행중인 프로그램에서 메모리 누출(leak)/오염(corruption)을 찾아낼 수 있다. 그 외의 Cachegrind, Helgrind 툴을 사용하여 캐쉬 프로파일링을 하거나, 멀티 쓰레드에서의 데이타 경쟁을 발견을 할 수 있다. 이 프로그램은 Julian Seward가 개발했다.

1.2 목적

이 문서는 간단한 Valgrind의 사용법을 설명한다. - 현재(1 Feb 2005)는 Memcheck 툴의 사용법에 관해서만 설명한다. - 더 자세한 내용을 알고 싶다면 [http]http://valgrind.kde.org/docs.html에서 Valgrind 관련 문서들을 볼 수 있다.

1.3 주의

현재(1 Feb 2005) Valgrind의 안정 버전은 2.2.0 이고, 버전 2.0.X와 2.2.X은 사용법이 다르다. 이 문서는 2.2.X 버전의 Valgrind의 사용법을 다룬다.

2 Valginrd 설치

2.1 Valgrind 소스 얻기

Valgrind의 소스는 Valgrind 홈페이지의 다운로드 페이지에서 받을 수 있다.
Valgrind 다운로드 페이지

2.2 설치

위의 페이지에서 bzip2 형식으로 압축된 압축 파일을 풀고, 설치한다.

    # tar xvjf valgrind-2.2.0.tar.bz2
    # cd valgrind-2.2.0
    # ./configure
    # make
    # make install

3 Valgrind 사용

3.1 Valginrd의 각 툴에 대해서

3.1.1 Memcheck

Valgrind의 Memcheck는 다음과 같은 경우를 발견하고 보고한다.
  • 초기화되지 않은 메모리의 사용
  • free된 메모리에 읽기/쓰기를 시도하는 경우
  • malloc된 메모리 블럭 외에 읽기/쓰기를 시도하는 경우
  • stack의 부적절한 지역에 읽기/쓰기가 시도되는 경우
  • 메모리 누출 - malloc되고 free되지 않은 메모리
  • 초기화되지 않거나 주소를 알 수 없는 메모리가 시스템 호출로 넘겨지는 경우
  • memcpy()와 관련된 함수에서 src와 dst 포인터가 겹치는 경우
  • 몇 가지의 POSIX pthreads API의 잘못된 사용

3.1.2 Addrcheck

Addrcheck는 Memcheck의 가벼운 버전이다.

3.1.3 Cachegrind

Cachegrind는 프로그램의 캐시 프로파일링을 한다.

3.1.4 Helgrind

Helgrind는 멀티스레드 프로그램에서 데이터의 경쟁 상태를 발견한다.

3.1.5 그 밖의 툴

위에서 설명된 툴의 보다 자세한 설명이나 그 외의 툴들에 관한 설명은 [http]Valgrind 2.2.0 매뉴얼(http://developer.kde.org/~sewardj/docs-2.2.0/manual.html)을 참조한다.

3.2 Valgind 사용

3.2.1 Valgrind 실행

Valgrind는 아래의 usage와 같이 valgrind 이후에 쓰고 싶은 tool의 이름을 쓰고 마지막에 디버깅이나 프로파일링을 할 프로그램과 인자를 쓰면 된다. 자세한 것은 'valgrind --help'로 볼 수 있다.

    usage: valgrind --tool=<toolname> [options] prog-and-args
예) 다음과 같이 'ps'의 메모리 사용을 체크할 수 있다.

    # valgrind --tool=memcheck ps -ax

3.2.2 Valgrind의 Memcheck 사용 예

예제 1

#include <stdio.h>
#include <stdlib.h>

int main()
{
    int p, t;
    char * pc;

    if (p == 5) {       /* 초기화되지 않은 메모리의 사용 */
        t = p + 1;
    }

    printf("%d is not initialized\n", p); /* 초기화되지 않은 메모리의 사용 */

    pc = (char *)malloc(sizeof(char) * 10);

    /* pc가 free되지 않음 */

    return 0;
}
위와 같은 예제를 Valgrind를 사용하여 실행하면 다음과 같은 결과가 나온다. 에러 리포트 설명은 주석(';'으로 시작하는 문장)으로 달았다.
# valgrind --tool=memcheck ./a.out
==27949== Memcheck, a memory error detector for x86-linux.
==27949== Copyright (C) 2002-2004, and GNU GPL'd, by Julian Seward et al.
==27949== Using valgrind-2.2.0, a program supervision framework for x86-linux.
==27949== Copyright (C) 2000-2004, and GNU GPL'd, by Julian Seward et al.
==27949== For more details, rerun with: -v

; 앞의 '==26306=='은 프로세스 ID를 뜻한다.

==27949==
==27949== Conditional jump or move depends on uninitialised value(s)
==27949==    at 0x804844A: main (in /home/deicide/play/a.out)
==27949==

; 위의 에러는 main 함수에서 if (p == 5) {...} 에서
; p가 초기화 되지 않았음을 나타낸다.

==27949== Use of uninitialised value of size 4
==27949==    at 0x1B967329: _IO_vfprintf (in /lib/libc-2.2.4.so)
==27949==    by 0x1B96FC11: _IO_printf (printf.c:33)
==27949==    by 0x8048463: main (in /home/deicide/play/a.out)
==27949==
==27949== Conditional jump or move depends on uninitialised value(s)
==27949==    at 0x1B966C2C: _IO_vfprintf (in /lib/libc-2.2.4.so)
==27949==    by 0x1B96FC11: _IO_printf (printf.c:33)
==27949==    by 0x8048463: main (in /home/deicide/play/a.out)
==27949==
==27949== Conditional jump or move depends on uninitialised value(s)
==27949==    at 0x1B966E93: _IO_vfprintf (in /lib/libc-2.2.4.so)
==27949==    by 0x1B96FC11: _IO_printf (printf.c:33)
==27949==    by 0x8048463: main (in /home/deicide/play/a.out)
==27949==
==27949== Conditional jump or move depends on uninitialised value(s)
==27949==    at 0x1B966EB4: _IO_vfprintf (in /lib/libc-2.2.4.so)
==27949==    by 0x1B96FC11: _IO_printf (printf.c:33)
==27949==    by 0x8048463: main (in /home/deicide/play/a.out)
==27949==
==27949== Conditional jump or move depends on uninitialised value(s)
==27949==    at 0x1B966ED5: _IO_vfprintf (in /lib/libc-2.2.4.so)
==27949==    by 0x1B96FC11: _IO_printf (printf.c:33)
==27949==    by 0x8048463: main (in /home/deicide/play/a.out)
==27949==
==27949== Conditional jump or move depends on uninitialised value(s)
==27949==    at 0x1B966F12: _IO_vfprintf (in /lib/libc-2.2.4.so)
==27949==    by 0x1B96FC11: _IO_printf (printf.c:33)
==27949==    by 0x8048463: main (in /home/deicide/play/a.out)
134518296 is not initialized

; 위의 에러들은 printf("%d is not initialized\n", p); 에서 
; p가 초기화 되지 않았음으로 나타나는 에러들이다.

==27949==
==27949== ERROR SUMMARY: 15 errors from 7 contexts (suppressed: 19 from 2)
==27949== malloc/free: in use at exit: 10 bytes in 1 blocks.
==27949== malloc/free: 1 allocs, 0 frees, 10 bytes allocated.

; malloc/free 된 block의 상태를 보고한다.
; 10bytes가 malloc되고 free가 없었음을 알 수 있다.

==27949== For a detailed leak analysis,  rerun with: --leak-check=yes
==27949== For counts of detected errors, rerun with: -v

; 메모리 누출의 자세한 보고를 위해서 --leak-chcek=yes 옵션을 줄 수 있다
옵션으로 '--leak-check=yes'를 줄 경우 아래와 같이 메모리 누출에 대한 자세한 보고를 볼 수 있다. 아래는 동일한 Sample을 '--leak-check=yes' 옵션을 줘서 실행한 결과의 메모리 누출 결과 부분이다. 각각의 definitely leak, possibly lost, still reachable, suppressed가 뜻하는 것은 [http]Valgrind FAQ(http://valgrind.kde.org/faq.html)의 6.2 항목에 자세히 나와있다.
# valgrind --tool=memcheck --leak-check=yes ./a.out

...

==24404== ERROR SUMMARY: 15 errors from 7 contexts (suppressed: 19 from 2)
==24404== malloc/free: in use at exit: 10 bytes in 1 blocks.
==24404== malloc/free: 1 allocs, 0 frees, 10 bytes allocated.
==24404== For counts of detected errors, rerun with: -v
==24404== searching for pointers to 1 not-freed blocks.
==24404== checked 1411896 bytes.
==24404==
==24404==
==24404== 10 bytes in 1 blocks are definitely lost in loss record 1 of 1
==24404==    at 0x1B903E85: malloc (vg_replace_malloc.c:131)
==24404==    by 0x8048470: main (in /home/deicide/play/a.out)
==24404==
==24404== LEAK SUMMARY:
==24404==    definitely lost: 10 bytes in 1 blocks.
==24404==    possibly lost:   0 bytes in 0 blocks.
==24404==    still reachable: 0 bytes in 0 blocks.
==24404==         suppressed: 0 bytes in 0 blocks.
==24404== Reachable blocks (those to which a pointer was found) are not shown.
==24404== To see them, rerun with: --show-reachable=yes
다른 툴이나 옵션에 대해서는 [http]Valgrind full documentation(http://developer.kde.org/~sewardj/docs-2.2.0/manual.html)을 참조한다.

4 참조


출처 : http://bibreen.cafe24.com/

728x90

댓글