linux에서 메모리 유출을 디버깅하는 유리한 장치 Valgrind

Valgrind의 주저자인 줄리엔 세워드는 올해 Google-O'Reilly 오픈소스 대상 중 하나인 Best Tool Maker를 수상했다.그의 작품을 함께 봅시다.Valgrind는 리눅스에서 실행되는 모방 기술을 기반으로 한 프로그램 디버깅과 분석 도구로, 소프트웨어 합성 CPU와 일련의 작은 도구를 포함하고 있으며, 모든 도구는 디버깅, 분석, 테스트 등을 수행할 수 있다.Valgrind는 메모리 유출과 메모리 위반을 감지할 수 있고, 캐치의 사용도 분석할 수 있는 등 유연하고 가볍고 강력하며 프로그램 오류의 심장을 직통할 수 있어 프로그래머의 스위스 군도라고 할 수 있다.
자세한 설명서는 Valgrind Documentation을 참조하십시오.
하나.Valgrind 개요
Valgrind의 최신 버전은 3.2.0이며 일반적으로 다음 도구를 포함합니다.
1.Memcheck
프로그램에서 발생하는 메모리 문제를 감지하는 데 가장 자주 사용하는 도구입니다. 메모리에 대한 읽기와 쓰기가 모두 검출되고,malloc ()/free ()/new/delete에 대한 모든 호출이 포착됩니다.따라서 다음과 같은 문제를 감지할 수 있습니다.
1. 초기화되지 않은 메모리의 사용;
2. 풀린 메모리 블록을 읽기/쓰기;
3.malloc분배를 초과한 메모리 블록을 읽기/쓰기;
4. 부적절한 창고의 메모리 블록을 읽거나 쓰기;
5. 메모리 유출은 메모리를 가리키는 바늘을 영원히 잃어버린다.
6. 올바르지 않은malloc/free 또는 new/delete가 일치합니다.
7,memcpy() 관련 함수 중의 dst와 src 포인터가 중첩됩니다.
이런 문제들은 종종 C/C++ 프로그래머들이 가장 골치 아픈 문제들이고Memcheck이 이곳에서 큰 도움을 주었다.
2.Callgrind
gprof와 유사한 분석 도구이지만 프로그램의 운행에 대한 관찰은 더욱 세밀하고 우리에게 더 많은 정보를 제공할 수 있다.gprof와 달리 원본 코드를 컴파일할 때 특별한 옵션을 추가할 필요는 없지만 디버깅 옵션을 추가하는 것이 추천합니다.Callgrind는 프로그램이 실행될 때의 데이터를 수집하고 함수 호출 관계도를 작성하며 cache 시뮬레이션을 선택적으로 할 수 있습니다.실행이 끝날 때, 분석 데이터를 파일에 기록합니다.callgrind_annotate는 이 파일의 내용을 읽을 수 있는 형식으로 바꿀 수 있습니다.
3.Cachegrind
Cache 분석기는 CPU의 1급 캐시 I1, Dl, 2급 캐시를 모의하여 프로그램 중cache의 분실과 명중을 정확하게 가리킨다.필요하면,cache 분실 횟수, 메모리 인용 횟수, 줄마다 코드, 함수마다, 모듈마다, 프로그램 전체에 발생하는 지령수를 제공할 수 있습니다.이것은 프로그램을 최적화하는 데 매우 큰 도움이 된다.
4.Helgrind
그것은 주로 다중 루틴 프로그램에서 발생하는 경쟁 문제를 검사하는 데 쓰인다.Helgrind는 메모리에 여러 개의 스레드가 접근하고 일관되게 잠겨 있지 않은 구역을 찾는다. 이런 구역은 종종 스레드 사이의 동기화를 잃고 발굴하기 어려운 오류를 초래할 수 있다.Helgrind는'Eraser'라는 경쟁 검출 알고리즘을 구현하고 오류를 보고하는 횟수를 줄이도록 개선했다.그러나 헬릭슨은 여전히 실험 단계에 있다.
5. Massif
창고 분석기는 프로그램이 창고에 얼마나 많은 메모리를 사용했는지 측정할 수 있으며, 창고 관리 블록과 창고의 크기를 알려준다.Massif는 메모리의 사용을 줄이는 데 도움을 줄 수 있다. 가상 메모리를 가진 현대 시스템에서 프로그램의 실행을 가속화시키고 프로그램이 교환 구역에 머무를 확률을 줄일 수 있다.
이 밖에 lackey와nulgrind도 제공한다.Lackey는 소형 도구로 거의 사용되지 않는다.Nulgrind은 개발자에게 도구를 만드는 방법만 보여 줍니다.소개 안 할게요.
둘.Valgrind 사용
valgrind 명령의 형식은 다음과 같이 매우 간단합니다.
valgrind [valgrind-options] your-prog [your-prog options]
몇 가지 일반적인 옵션은 다음과 같습니다.
옵션
역할
-h --help
도움말 정보를 표시합니다.
--version
valgrind 커널의 버전을 표시합니다. 도구마다 버전이 있습니다.
-q --quiet
오류 메시지만 인쇄할 수 있도록 조용히 실행하십시오.
-v --verbose
더 자세한 정보를 인쇄합니다.
--tool= [default: memcheck]
가장 일반적인 옵션입니다.valgrind에서 toolname이라는 도구를 실행합니다.도구 이름을 생략하면memcheck을 기본적으로 실행합니다.
--db-attach= [default: no]
디버그 오류를 조정하기 위해 디버그에 연결합니다.
우리는 예를 통해 그것의 구체적인 사용을 보았다.다음과 같이 메모리 누수가 있는 C 프로그램을 구성했습니다.
#include <stdlib.h>
#include <stdio.h>
void f(void)
{
    int* x = malloc(10 * sizeof(int));
    x[10] = 0; // problem 1: heap block overrun
    } // problem 2: memory leak -- x not freed
    int main(void)
    {
    int i;
    f();
    printf("i=%d
",i); //problem 3: use uninitialised value. return 0; }

memleak로 저장합니다.c를 컴파일한 다음valgrind로 검사합니다.
$ gcc -Wall -o memleak memleak.c
$ valgrind --tool=memcheck ./memleak
우리는 다음과 같은 오류 정보를 얻었다.
==3649== Invalid write of size 4
==3649== at 0x80483CF: f (in/home/wangcong/memleak)
==3649== by 0x80483EC: main (in/home/wangcong/memleak)
==3649== Address 0x4024050 is 0 bytes after a block of size 40 alloc'd
==3649== at 0x40051F9: malloc (vg_replace_malloc.c:149)
==3649== by 0x80483C5: f (in/home/wangcong/memleak)
==3649== by 0x80483EC: main (in/home/wangcong/memleak)
앞에 있는 3649는 프로그램이 실행될 때의 프로세스 번호입니다.첫 번째 줄은 잘못된 유형을 알려주는 것입니다. 여기는 불법 기록입니다.다음은main()에서 호출된 f() 함수에서 오류가 발생한 위치를 알려 줍니다.
==3649== Use of uninitialised value of size 4
==3649== at 0xC3A264: _itoa_word (in/lib/libc-2.4.so)
==3649== by 0xC3E25C: vfprintf (in/lib/libc-2.4.so)
==3649== by 0xC442B6: printf (in/lib/libc-2.4.so)
==3649== by 0x80483FF: main (in/home/wangcong/memleak)
이 오류는main ()에서 호출된 printf () 함수에서 초기화되지 않은 값을 사용합니다.이 함수 호출 관계는 창고를 통해 추적되기 때문에, 특히 C++의 STL을 사용할 때 매우 많을 때가 있습니다.다른 일부 오류는 초기화되지 않은 값을libc 함수에 전달했기 때문에 검출되었습니다.프로그램 실행이 끝난 후에valgrind는 작은 요약을 제시했다.
==3649== ERROR SUMMARY: 20 errors from 6 contexts (suppressed: 12 from 1)
==3649== malloc/free: in use at exit: 40 bytes in 1 blocks.
==3649== malloc/free: 1 allocs, 0 frees, 40 bytes allocated.
==3649== For counts of detected errors, rerun with: -v
==3649== searching for pointers to 1 not-freed blocks.
==3649== checked 47,256 bytes.
==3649==
==3649== LEAK SUMMARY:
==3649== definitely lost: 40 bytes in 1 blocks.
==3649== possibly lost: 0 bytes in 0 blocks.
==3649== still reachable: 0 bytes in 0 blocks.
==3649== suppressed: 0 bytes in 0 blocks.
==3649== Use --leak-check=full to see details of leaked memory.
우리는 얼마나 많은 메모리를 분배하고 방출했는지, 얼마나 많은 메모리가 누출되었는지 똑똑히 알 수 있다.이것은 우리가 메모리 유출을 찾는 데 매우 편리하다.그런 다음 프로그램을 다시 컴파일하고 디버거를 바인딩합니다.
$ gcc -Wall -ggdb -o memleak memleak.c
$ valgrind --db-attach=yes --tool=memcheck ./memleak
오류가 발생하면 valgrind에서 디버거를 자동으로 시작합니다. (일반적으로 gdb)
==3893== ---- Attach to debugger ? --- [Return/N/n/Y/y/C/c] ---- y
starting debugger
==3893== starting debugger with cmd:/usr/bin/gdb -nw/proc/3895/fd/1014 3895
gdb를 종료한 후에 우리는valgrind로 돌아가서 프로그램을 계속 실행할 수 있습니다.
아니면 위의 프로그램으로 캘린더를 사용하여 그 효율을 분석해 봅시다.
$ valgrind --tool=callgrind ./memleak
Callgrind는 많은 출력을 하고, 마지막으로 현재 디렉터리에 파일을 생성합니다:callgrind.out.pid.콜린드로annotate를 사용하여 다음을 확인합니다.
$ callgrind_annotate callgrind.out.3949
상세한 정보가 열거되었다.그리고,callgrind가 프로그램을 실행할 때,callgrind 를 사용할 수 있습니다프로그램의 실행을 관찰할 뿐만 아니라, 프로그램의 실행을 방해하지 않는다.
다시 한 번 cachegrind의 표현을 살펴보자.
$ valgrind --tool=cachegrind ./memleak
다음과 같은 정보가 제공됩니다.
==4073== I refs: 147,500
==4073== I1 misses: 1,189
==4073== L2i misses: 679
==4073== I1 miss rate: 0.80%
==4073== L2i miss rate: 0.46%
==4073==
==4073== D refs: 61,920 (46,126 rd + 15,794 wr)
==4073== D1 misses: 1,759 ( 1,545 rd + 214 wr)
==4073== L2d misses: 1,241 ( 1,062 rd + 179 wr)
==4073== D1 miss rate: 2.8% ( 3.3% + 1.3% )
==4073== L2d miss rate: 2.0% ( 2.3% + 1.1% )
==4073==
==4073== L2 refs: 2,948 ( 2,734 rd + 214 wr)
==4073== L2 misses: 1,920 ( 1,741 rd + 179 wr)
==4073== L2 miss rate: 0.9% ( 0.8% + 1.1% )
위에 있는 것은 명령 캐시, I1과 L2i 캐시, 액세스 정보입니다. 전체 액세스 횟수, 분실 횟수, 분실률을 포함합니다.
중간에는 데이터 캐시, D1과 L2d 캐시, 방문에 대한 정보, 아래의 L2 캐시에 대한 단독 정보가 있습니다.Cachegrind도 cachegrind라는 파일을 생성합니다.out.pid, cgannotate에서 읽습니다.출력은 더 자세한 목록입니다.Massif의 사용은cachegrind와 유사하지만,massif라는 이름도 생성합니다.pid.ps의 PostScript 파일에는 스택의 사용 상황을 설명하는 색상 그림만 있습니다.
이상은valgrind의 사용을 간단하게 보여 주었을 뿐입니다. 더 많은 정보는 첨부된 문서에서 얻을 수 있고valgrind의 홈페이지를 방문할 수 있습니다.http://www.valgrind.org.valgrind를 정확하고 합리적으로 사용하는 것을 습득하는 것은 디버깅 프로그램에 큰 도움이 될 것이다.
원본 주소:http://wangcong.org/articles/valgrind.html

좋은 웹페이지 즐겨찾기