Public/tip & tech

valgrind

quantapia 2009. 5. 12. 17:57

간단한 사용법

$ valgrind --leak-resolution=high --trace-malloc=yes --leak-check=yes --show-reachable=yes -v [프로그램 전체 경로]  
$ valgrind --leak-resolution=high  --leak-check=yes --show-reachable=yes -v [프로그램 전체 경로]  

$ valgrind --db-attach=yes --leak-resolution=high --leak-check=yes --show-reachable=yes -v ./test_hanl 
 
실행이 끝난 다음에 malloc/free 된 메모리들에 대한 현황을 ERROR SUMMARY라는 이름으로 알려줍니다. leak된 것들이 있다면 어떤 종류이고 어떤 내용이 들어있는지 등등을 자세히 알려주니 그것을 보시면 디버깅이 손쉬울 겁니다. 혹 출력되는 메시지가 너무 많아 방해가 되면 valgrind --trace-malloc=yes 를 빼주셔도 이 경우에는 별 상관 없을겁니다. malloc/free 될때마다 뿌려주는 메시지를 출력안하는 것입니다.

만약 한번의 alloc에 대해 두번의 free가 가해졌다면 아래와 같은 메시지가 그 위치를 알려줍니다. 보시다시피 main.c의 52번째줄에서 이미 free한 메모리 블럭에 대해 main.c의 53번째줄에서 잘못된 free를 수행한 걸로 나옵니다.

 
ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)  
==29279==  
==29279== 1 errors in context 1 of 1:  
==29279== Invalid free() / delete / delete[]  
==29279==    at 0x40025E87: free (in /usr/lib/valgrind/vgskin_memcheck.so)  
==29279==    by 0x80489C3: main (main.c:53)  
==29279==    by 0x4024190A: __libc_start_main (in /lib/libc-2.3.2.so)  
==29279==    by 0x80488E0: (within /home/youlsa/src/montgomery/actiontag)  
==29279==    Address 0x4109C024 is 0 bytes inside a block of size 200 free'd  
==29279==    at 0x40025E87: free (in /usr/lib/valgrind/vgskin_memcheck.so)  
==29279==    by 0x80489B2: main (main.c:52)  
==29279==    by 0x4024190A: __libc_start_main (in /lib/libc-2.3.2.so)  
==29279==    by 0x80488E0: (within /home/youlsa/src/montgomery/actiontag)  
==29279== IN SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)  

Advanced using of valgrind

1. 우선 소스를 -g 옵션으로 컴파일 할것을 추천한다.

    안해도 에러를 잡을수 있으나, 보다 정확하고 이해하기 쉬운 에러 레포트를 뽑을 수 있다.

2. Memcheck 옵션을 쓸때 주의점
    컴파일할때 optimization level 이 02 또는 그 이상일때 Memcheck가 오동작 할수 있다.
    -0 옵션을 쓸 것을 제안한다. 옵티마이즈도 하면서 오동작 가능성을 최대한 줄일수 있다.

Meanning of Error code

  • Invalid read of size 4
    • 잘못된 메모리 번지를 가르킬때 발생한다. 주로 파라미터의 범위를 검사하지 않았을때 프로그래머가 의도하지 않은 인덱스가 넘어와 발생한다.
    • 모든 인덱스의 범위를 체크하는건 상당히 귀찮은 일이다. 그러나 그것때문에 디버깅하는건 몇백배 귀찮은 일이다.

  • Conditional jump or move depends on uninitialised value(s)
    • 변수 초기화 없이 사용되는 경우, 경우에 따라 문제가 되지 않을 수도 있지만 초기화하지 않은 변수로 배열을 접근할 경우 발생할수 있다.

uninitialised value of size 4

#define TEST    "TEST" 
 
int main() 
{ 
    int i; 
    char    buffer[1024]; 
 
    printf("%c\n",buffer[i]); 
} 
==16814== Use of uninitialised value of size 4 
==16814==    at 0x8048393: main (test.c:11) 
==16814== 
==16814== Invalid read of size 1 
==16814==    at 0x8048393: main (test.c:11) 
==16814==  Address 0xBF3FB5A4 is not stack'd, malloc'd or (recently) free'd 
==16814== 
==16814== Process terminating with default action of signal 11 (SIGSEGV): dumping core 
==16814==  Access not within mapped region at address 0xBF3FB5A4 
==16814==    at 0x8048393: main (test.c:11) 
==16814== 
==16814== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 14 from 1) 
==16814== malloc/free: in use at exit: 0 bytes in 0 blocks. 
==16814== malloc/free: 0 allocs, 0 frees, 0 bytes allocated. 
==16814== For counts of detected errors, rerun with: -v 
==16814== No malloc'd blocks -- no leaks are possible. 
 

Conditional jump or move depends on uninitialised value

int main() 
{ 
    int i = 1; 
    char    buffer[1024]; 
 
    printf("%s\n",&buffer[i]); 
}