1.1 Valgrind란?
Valgrind는 Linux-x86 용 실행 파일의 디버깅과 프로파일링을 위한 오픈 소스 툴이다. Valgrind는 Memcheck이나 Addrcheck 툴을 사용하여 실행중인 프로그램에서 메모리 누출(leak)/오염(corruption)을 찾아낼 수 있다. 그 외의 Cachegrind, Helgrind 툴을 사용하여 캐쉬 프로파일링을 하거나, 멀티 쓰레드에서의 데이타 경쟁을 발견을 할 수 있다. 이 프로그램은 Julian Seward가 개발했다.1.2 목적
이 문서는 간단한 Valgrind의 사용법을 설명한다. - 현재(1 Feb 2005)는 Memcheck 툴의 사용법에 관해서만 설명한다. - 더 자세한 내용을 알고 싶다면 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의 사용법을 다룬다.Valgrind 다운로드 페이지
2.2 설치
위의 페이지에서 bzip2 형식으로 압축된 압축 파일을 풀고, 설치한다.# tar xvjf valgrind-2.2.0.tar.bz2 # cd valgrind-2.2.0 # ./configure # make # make install
- 초기화되지 않은 메모리의 사용
- free된 메모리에 읽기/쓰기를 시도하는 경우
- malloc된 메모리 블럭 외에 읽기/쓰기를 시도하는 경우
- stack의 부적절한 지역에 읽기/쓰기가 시도되는 경우
- 메모리 누출 - malloc되고 free되지 않은 메모리
- 초기화되지 않거나 주소를 알 수 없는 메모리가 시스템 호출로 넘겨지는 경우
- memcpy()와 관련된 함수에서 src와 dst 포인터가 겹치는 경우
- 몇 가지의 POSIX pthreads API의 잘못된 사용
3.1.2 Addrcheck
Addrcheck는 Memcheck의 가벼운 버전이다.3.1.5 그 밖의 툴
위에서 설명된 툴의 보다 자세한 설명이나 그 외의 툴들에 관한 설명은 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가 뜻하는 것은 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
다른 툴이나 옵션에 대해서는 Valgrind full documentation(http://developer.kde.org/~sewardj/docs-2.2.0/manual.html)을 참조한다.
4 참조
- Valgrind 홈페이지
- Valgrind full documentation
- Debugging Memory Problems, by Steve Best (Valgrind 1.X.X 기반 문서)
- Valgrind HOWTO, by Deepak P. and Sandeep S. (Valgrind 1.X.X 기반 문서)
- The design and implementation of Valgrind
출처 : http://bibreen.cafe24.com/
728x90
댓글