Valgrind - 윈디하나의 솔라나라
|
windy@wl ~/src $ wget https://sourceware.org/pub/valgrind/valgrind-3.20.0.tar.bz2
windy@wl ~/src $ tar xvfj valgrind-3.20.0.tar.bz2
windy@wl ~/src $ cd valgrind-3.20.0
windy@wl ~/src/valgrind-3.20.0 $ cat README.solaris 1)
windy@wl ~/src/valgrind-3.20.0 $ ./configure CC='gcc' CXX='g++' --enable-only64bit
windy@wl ~/src/valgrind-3.20.0 $ make
windy@wl ~/src/valgrind-3.20.0 $ sudo make install
1) 각 OS마다 README 파일을 제공해준다. valgrind 를 사용함에 있어 운영체제별 제한사항이나 유의사항에 대해 나와있다. 꼭 읽어보자.
추가적인 옵션을 지정하지 않으면 valgrind 는 Memcheck 툴을 실행한다. 아래는 ls(1)명령어를 실행해 메모리를 검사한 화면이다.
windy@wl ~/valgrind $ valgrind ls ==14679== Memcheck, a memory error detector ==14679== Copyright (C) 2002-2022, and GNU GPL'd, by Julian Seward et al. ==14679== Using Valgrind-3.20.0 and LibVEX; rerun with -h for copyright info ==14679== Command: ls ==14679== --14679-- WARNING: Serious error when reading debug info --14679-- When reading debug info from /lib/amd64/ld.so.1: --14679-- Can't make sense of .data section mapping ... ==14679== ==14679== HEAP SUMMARY: ==14679== in use at exit: 95,989 bytes in 56 blocks ==14679== total heap usage: 132 allocs, 76 frees, 103,923 bytes allocated ==14679== ==14679== LEAK SUMMARY: ==14679== definitely lost: 0 bytes in 0 blocks ==14679== indirectly lost: 0 bytes in 0 blocks ==14679== possibly lost: 0 bytes in 0 blocks ==14679== still reachable: 95,989 bytes in 56 blocks ==14679== suppressed: 0 bytes in 0 blocks ==14679== Rerun with --leak-check=full to see details of leaked memory ==14679== ==14679== For lists of detected and suppressed errors, rerun with: -s ==14679== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
누수가 있는 경우 아래와 같이 출력된다.
windy@wl ~/valgrind $ wget https://www.solanara.net/contents/includes/memoryleak_leak.c windy@wl ~/valgrind $ cc -m64 -o leak memoryleak_leak.c
windy@wl ~/valgrind $ valgrind ./leak ==15661== Memcheck, a memory error detector ==15661== Copyright (C) 2002-2022, and GNU GPL'd, by Julian Seward et al. ==15661== Using Valgrind-3.20.0 and LibVEX; rerun with -h for copyright info ==15661== Command: ./leak ==15661== --15661-- WARNING: Serious error when reading debug info --15661-- When reading debug info from /lib/amd64/ld.so.1: --15661-- Can't make sense of .data section mapping ==15661== ==15661== HEAP SUMMARY: ==15661== in use at exit: 90 bytes in 3 blocks ==15661== total heap usage: 3 allocs, 0 frees, 90 bytes allocated ==15661== ==15661== LEAK SUMMARY: ==15661== definitely lost: 90 bytes in 3 blocks ==15661== indirectly lost: 0 bytes in 0 blocks ==15661== possibly lost: 0 bytes in 0 blocks ==15661== still reachable: 0 bytes in 0 blocks ==15661== suppressed: 0 bytes in 0 blocks ==15661== Rerun with --leak-check=full to see details of leaked memory ==15661== ==15661== For lists of detected and suppressed errors, rerun with: -s ==15661== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
windy@wl ~/valgrind $ valgrind --leak-check=full ./leak ==16068== Memcheck, a memory error detector ==16068== Copyright (C) 2002-2022, and GNU GPL'd, by Julian Seward et al. ==16068== Using Valgrind-3.20.0 and LibVEX; rerun with -h for copyright info ==16068== Command: ./leak ==16068== --16068-- WARNING: Serious error when reading debug info --16068-- When reading debug info from /lib/amd64/ld.so.1: --16068-- Can't make sense of .data section mapping ==16068== ==16068== HEAP SUMMARY: ==16068== in use at exit: 90 bytes in 3 blocks ==16068== total heap usage: 3 allocs, 0 frees, 90 bytes allocated ==16068== ==16068== 10 bytes in 1 blocks are definitely lost in loss record 1 of 3 ==16068== at 0xFFFA04E97: malloc (vg_replace_malloc.c:409) ==16068== by 0x400E33: main (in /export/home/windy/t/leak) ==16068== ==16068== 30 bytes in 1 blocks are definitely lost in loss record 2 of 3 ==16068== at 0xFFFA04E97: malloc (vg_replace_malloc.c:409) ==16068== by 0x400E43: main (in /export/home/windy/t/leak) ==16068== ==16068== 50 bytes in 1 blocks are definitely lost in loss record 3 of 3 ==16068== at 0xFFFA04E97: malloc (vg_replace_malloc.c:409) ==16068== by 0x400E53: main (in /export/home/windy/t/leak) ==16068== ==16068== LEAK SUMMARY: ==16068== definitely lost: 90 bytes in 3 blocks ==16068== indirectly lost: 0 bytes in 0 blocks ==16068== possibly lost: 0 bytes in 0 blocks ==16068== still reachable: 0 bytes in 0 blocks ==16068== suppressed: 0 bytes in 0 blocks ==16068== ==16068== For lists of detected and suppressed errors, rerun with: -s ==16068== ERROR SUMMARY: 3 errors from 3 contexts (suppressed: 0 from 0)
이 툴의 이름은 메모리 오류 감지기
이고, 그 중에 메모리 누수를 감지한 예를 들었다. 다른 기능에 대해서는 매뉴얼을 참고하자.
Cachegrind 툴은 프로그램 실행시 CPU의 캐시 메모리에 대한 정보를 보여준다. CPU의 I1, D1, L2 캐시 정보의 히트율, 미스율 등을 볼 수 있는데, 미스율이 높다면 프로그램 설계를 조정하거나, CPU에 최적화 시켜서 컴파일 해야 할 것이다.
windy@wl ~/valgrind $ valgrind --tool=cachegrind ls ==16442== Cachegrind, a cache and branch-prediction profiler ==16442== Copyright (C) 2002-2017, and GNU GPL'd, by Nicholas Nethercote et al. ==16442== Using Valgrind-3.20.0 and LibVEX; rerun with -h for copyright info ==16442== Command: ls ==16442== --16442-- WARNING: Serious error when reading debug info --16442-- When reading debug info from /lib/amd64/ld.so.1: --16442-- Can't make sense of .data section mapping ... ==16442== ==16442== I refs: 877,606 ==16442== I1 misses: 4,445 ==16442== LLi misses: 2,377 ==16442== I1 miss rate: 0.51% ==16442== LLi miss rate: 0.27% ==16442== ==16442== D refs: 381,851 (252,196 rd + 129,655 wr) ==16442== D1 misses: 7,708 ( 5,459 rd + 2,249 wr) ==16442== LLd misses: 5,936 ( 3,956 rd + 1,980 wr) ==16442== D1 miss rate: 2.0% ( 2.2% + 1.7% ) ==16442== LLd miss rate: 1.6% ( 1.6% + 1.5% ) ==16442== ==16442== LL refs: 12,153 ( 9,904 rd + 2,249 wr) ==16442== LL misses: 8,313 ( 6,333 rd + 1,980 wr) ==16442== LL miss rate: 0.7% ( 0.6% + 1.5% )
Cachegrind로 실행시키면 현재디렉토리에 cachegrind.out 이라는 아스키 파일이 생성된다. cg_annotate(1)을 사용해 좀 더 쉽게 볼 수 있다.
windy@wl ~/valgrind $ cg_annotate cachegrind.out.18899 -------------------------------------------------------------------------------- I1 cache: 32768 B, 64 B, 8-way associative D1 cache: 32768 B, 64 B, 8-way associative LL cache: 3145728 B, 64 B, 12-way associative Command: ls Data file: cachegrind.out.16442 Events recorded: Ir I1mr ILmr Dr D1mr DLmr Dw D1mw DLmw Events shown: Ir I1mr ILmr Dr D1mr DLmr Dw D1mw DLmw Event sort order: Ir I1mr ILmr Dr D1mr DLmr Dw D1mw DLmw Thresholds: 0.1 100 100 100 100 100 100 100 100 Include dirs: User annotated: Auto-annotation: on -------------------------------------------------------------------------------- Ir I1mr ILmr Dr D1mr DLmr Dw D1mw DLmw -------------------------------------------------------------------------------- 877,606 (100.0%) 4,445 (100.0%) 2,377 (100.0%) 252,196 (100.0%) 5,459 (100.0%) 3,956 (100.0%) 129,655 (100.0%) 2,249 (100.0%) 1,980 (100.0%) PROGRAM TOTALS -------------------------------------------------------------------------------- Ir I1mr ILmr Dr D1mr DLmr Dw D1mw DLmw file:function -------------------------------------------------------------------------------- 697,985 (79.53%) 2,818 (63.40%) 1,328 (55.87%) 204,210 (80.97%) 4,867 (89.16%) 3,575 (90.37%) 96,046 (74.08%) 1,558 (69.28%) 1,396 (70.51%) ???:??? 17,559 ( 2.00%) 98 ( 2.20%) 33 ( 1.39%) 4,545 ( 1.80%) 12 ( 0.22%) 7 ( 0.18%) 4,613 ( 3.56%) 24 ( 1.07%) 16 ( 0.81%) ???:_ndoprnt_s 14,398 ( 1.64%) 10 ( 0.22%) 6 ( 0.25%) 4,279 ( 1.70%) 6 ( 0.11%) 4 ( 0.10%) 2,502 ( 1.93%) 1 ( 0.04%) 0 ???:mutex_lock_impl 13,904 ( 1.58%) 12 ( 0.27%) 5 ( 0.21%) 3,760 ( 1.49%) 1 ( 0.02%) 0 2,189 ( 1.69%) 0 0 ???:mutex_unlock 10,291 ( 1.17%) 87 ( 1.96%) 12 ( 0.50%) 1,942 ( 0.77%) 3 ( 0.05%) 2 ( 0.05%) 0 0 0 ???:strcmp 9,749 ( 1.11%) 24 ( 0.54%) 13 ( 0.55%) 3,009 ( 1.19%) 0 0 2,144 ( 1.65%) 40 ( 1.78%) 32 ( 1.62%) ???:_malloc_unlocked 8,044 ( 0.92%) 11 ( 0.25%) 4 ( 0.17%) 2,546 ( 1.01%) 0 0 1,324 ( 1.02%) 1 ( 0.04%) 0 ???:_ti_bind_clear 7,809 ( 0.89%) 97 ( 2.18%) 14 ( 0.59%) 3,753 ( 1.49%) 145 ( 2.66%) 108 ( 2.73%) 895 ( 0.69%) 14 ( 0.62%) 0 ???:handle_methods 5,751 ( 0.66%) 6 ( 0.13%) 3 ( 0.13%) 1,265 ( 0.50%) 27 ( 0.49%) 10 ( 0.25%) 68 ( 0.05%) 0 0 ???:findenv 5,306 ( 0.60%) 9 ( 0.20%) 3 ( 0.13%) 930 ( 0.37%) 55 ( 1.01%) 50 ( 1.26%) 0 0 0 ???:strlen 4,488 ( 0.51%) 38 ( 0.85%) 22 ( 0.93%) 1,455 ( 0.58%) 30 ( 0.55%) 23 ( 0.58%) 1,134 ( 0.87%) 29 ( 1.29%) 20 ( 1.01%) ???:memcpy 4,290 ( 0.49%) 4 ( 0.09%) 2 ( 0.08%) 1,300 ( 0.52%) 4 ( 0.07%) 1 ( 0.03%) 1,040 ( 0.80%) 1 ( 0.04%) 0 ???:do_malloc 3,872 ( 0.44%) 79 ( 1.78%) 3 ( 0.13%) 1,120 ( 0.44%) 1 ( 0.02%) 1 ( 0.03%) 815 ( 0.63%) 1 ( 0.04%) 1 ( 0.05%) ???:_ti_bind_guard 3,545 ( 0.40%) 26 ( 0.58%) 10 ( 0.42%) 213 ( 0.08%) 24 ( 0.44%) 14 ( 0.35%) 1,476 ( 1.14%) 240 (10.67%) 236 (11.92%) ???:memset 3,220 ( 0.37%) 9 ( 0.20%) 4 ( 0.17%) 560 ( 0.22%) 0 0 840 ( 0.65%) 5 ( 0.22%) 2 ( 0.10%) ???:vasprintf 3,190 ( 0.36%) 3 ( 0.07%) 3 ( 0.13%) 906 ( 0.36%) 2 ( 0.04%) 1 ( 0.03%) 450 ( 0.35%) 0 0 ???:_free_unlocked 2,795 ( 0.32%) 11 ( 0.25%) 5 ( 0.21%) 804 ( 0.32%) 0 0 726 ( 0.56%) 30 ( 1.33%) 23 ( 1.16%) ???:realfree 2,704 ( 0.31%) 4 ( 0.09%) 3 ( 0.13%) 1,248 ( 0.49%) 0 0 624 ( 0.48%) 0 0 ???:set_cancel_pending_flag 2,380 ( 0.27%) 8 ( 0.18%) 4 ( 0.17%) 280 ( 0.11%) 0 0 700 ( 0.54%) 5 ( 0.22%) 2 ( 0.10%) ???:vsnprintf 2,240 ( 0.26%) 6 ( 0.13%) 3 ( 0.13%) 630 ( 0.25%) 0 0 630 ( 0.49%) 0 0 ???:_dowrite 2,130 ( 0.24%) 6 ( 0.13%) 2 ( 0.08%) 426 ( 0.17%) 0 0 568 ( 0.44%) 0 0 ???:strlcpy 1,926 ( 0.22%) 6 ( 0.13%) 3 ( 0.13%) 502 ( 0.20%) 1 ( 0.02%) 1 ( 0.03%) 446 ( 0.34%) 3 ( 0.13%) 0 ???:cleanfree 1,878 ( 0.21%) 1 ( 0.02%) 1 ( 0.04%) 626 ( 0.25%) 0 0 626 ( 0.48%) 2 ( 0.09%) 1 ( 0.05%) ???:mutex_lock 1,875 ( 0.21%) 2 ( 0.04%) 2 ( 0.08%) 525 ( 0.21%) 0 0 450 ( 0.35%) 0 0 ???:free 1,748 ( 0.20%) 10 ( 0.22%) 10 ( 0.42%) 646 ( 0.26%) 9 ( 0.16%) 5 ( 0.13%) 266 ( 0.21%) 0 0 ???:coll_chr2weight_std 1,540 ( 0.18%) 6 ( 0.13%) 3 ( 0.13%) 140 ( 0.06%) 0 0 910 ( 0.70%) 0 0 ???:asprintf 1,440 ( 0.16%) 5 ( 0.11%) 5 ( 0.21%) 352 ( 0.14%) 0 0 192 ( 0.15%) 0 0 ???:putc 1,367 ( 0.16%) 23 ( 0.52%) 23 ( 0.97%) 189 ( 0.07%) 11 ( 0.20%) 11 ( 0.28%) 194 ( 0.15%) 0 0 ???:handle_ctype 1,367 ( 0.16%) 7 ( 0.16%) 3 ( 0.13%) 56 ( 0.02%) 2 ( 0.04%) 1 ( 0.03%) 298 ( 0.23%) 63 ( 2.80%) 63 ( 3.18%) ???:_smalloc 1,345 ( 0.15%) 2 ( 0.04%) 1 ( 0.04%) 393 ( 0.16%) 0 0 230 ( 0.18%) 0 0 ???:_malloc_roundup_size 1,341 ( 0.15%) 4 ( 0.09%) 2 ( 0.08%) 424 ( 0.17%) 2 ( 0.04%) 0 282 ( 0.22%) 0 0 ???:met_cache_check 1,326 ( 0.15%) 6 ( 0.13%) 2 ( 0.08%) 390 ( 0.15%) 0 0 312 ( 0.24%) 2 ( 0.09%) 1 ( 0.05%) ???:_ndoprnt 1,318 ( 0.15%) 3 ( 0.07%) 2 ( 0.08%) 348 ( 0.14%) 0 0 278 ( 0.21%) 0 0 ???:check_mes_pathlist 1,240 ( 0.14%) 2 ( 0.04%) 1 ( 0.04%) 298 ( 0.12%) 0 0 173 ( 0.13%) 0 0 ???:_malloc_process_allocated_chunk 1,224 ( 0.14%) 4 ( 0.09%) 2 ( 0.08%) 102 ( 0.04%) 0 0 102 ( 0.08%) 0 0 ???:calloc 1,186 ( 0.14%) 4 ( 0.09%) 4 ( 0.17%) 288 ( 0.11%) 0 0 225 ( 0.17%) 0 0 ???:_flsbuf 1,092 ( 0.12%) 4 ( 0.09%) 1 ( 0.04%) 390 ( 0.15%) 1 ( 0.02%) 0 312 ( 0.24%) 2 ( 0.09%) 2 ( 0.10%) ???:__get_current_locale_t 1,078 ( 0.12%) 8 ( 0.18%) 8 ( 0.34%) 83 ( 0.03%) 74 ( 1.36%) 73 ( 1.85%) 227 ( 0.18%) 73 ( 3.25%) 73 ( 3.69%) ???:signal_init 1,020 ( 0.12%) 12 ( 0.27%) 6 ( 0.25%) 140 ( 0.06%) 0 0 200 ( 0.15%) 0 0 ???:mutex_init
실행파일에 디버깅 정보가 있다면, 프로그램 소스 한줄 실행할 때 마다 캐시 정보가 출력된다. 이외에도 cg_diff(1)과 cg_merge(1)을 제공해준다. 자세한 것은 매뉴얼을 참고하자.
Callgrind 는 호출 내역을 도식화해서 보여주는 툴이다. valgrind 로 데이터를 추출해 callgrind_annotate(1)나 KCachegrind나 QCacheGrind(윈도용)으로 도식화한다.
windy@wl ~/valgrind $ valgrind --tool=callgrind ./leak ==4528== Callgrind, a call-graph generating cache profiler ==4528== Copyright (C) 2002-2017, and GNU GPL'd, by Josef Weidendorfer et al. ==4528== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info ==4528== Command: ./leak ==4528== ==4528== For interactive control, run 'callgrind_control -h'. ==4528== ==4528== Events : Ir ==4528== Collected : 471997 ==4528== ==4528== I refs: 471,997 windy@wl ~/valgrind $ callgrind_annotate callgrind.out.4528 callgrind_annotate callgrind.out.4528 -------------------------------------------------------------------------------- Profile data file 'callgrind.out.4528' (creator: callgrind-3.13.0) -------------------------------------------------------------------------------- I1 cache: D1 cache: LL cache: Timerange: Basic block 0 - 91623 Trigger: Program termination Profiled target: ./leak (PID 4528, part 1) Events recorded: Ir Events shown: Ir Event sort order: Ir Thresholds: 99 Include dirs: User annotated: Auto-annotation: off -------------------------------------------------------------------------------- Ir -------------------------------------------------------------------------------- 471,997 PROGRAM TOTALS -------------------------------------------------------------------------------- Ir file:function -------------------------------------------------------------------------------- 162,756 ???:_elf_reloc_relative [/lib/ld.so.1] 78,237 ???:elf_reloc [/lib/ld.so.1] 38,347 ???:elf_find_sym [/lib/ld.so.1] 20,485 ???:_malloc [/lib/ld.so.1] 19,677 ???:elf_hash [/lib/ld.so.1] 11,024 ???:_lookup_sym [/lib/ld.so.1] ...
Callgrind를 실행하는 도중 callgrind_control(1)을 실행해 제어할 수 있다. 자세한 것은 매뉴얼을 읽어보자.
Helgrind은 쓰레드 오류 감지기다. C/C++/Fortran 에서 POSIX pthreads 를 사용한 경우 잘못된 사용을 감지할 수 있다. 아래는 락을 걸지 않고 두개의 쓰레드에서 동일한 변수에 접근한 경우의 예다. tc01_simple_race.c 파일은 Valgrind 의 소스 아카이브에서 제공하는 파일이다.
windy@wl ~/valgrind $ cc -o race ~/src/valgrind-3.15.0/helgrind/tests/tc01_simple_race.c windy@wl ~/valgrind $ valgrind --tool=helgrind ./race ==12707== Helgrind, a thread error detector ==12707== Copyright (C) 2007-2017, and GNU GPL'd, by OpenWorks LLP et al. ==12707== Using Valgrind-3.15.0 and LibVEX; rerun with -h for copyright info ==12707== Command: ./race ==12707== ==12707== ---Thread-Announcement------------------------------------------ ==12707== ==12707== Thread #1 is the program's root thread ==12707== ==12707== ---Thread-Announcement------------------------------------------ ==12707== ==12707== Thread #2 was created ==12707== at 0x4FF2B665: __lwp_create (in /lib/libc.so.1) ==12707== by 0x4FF1253E: pthread_create (in /lib/libc.so.1) ==12707== by 0x4FF88592: pthread_create_WRK (hg_intercepts.c:427) ==12707== by 0x4FF890C3: pthread_create (hg_intercepts.c:478) ==12707== by 0x8050CA4: main (in /export/home/windy/valgrind/race) ==12707== ==12707== ---------------------------------------------------------------- ==12707== ==12707== Possible data race during read of size 4 at 0x8060F44 by thread #1 ==12707== Locks held: none ==12707== at 0x8050CDB: main (in /export/home/windy/valgrind/race) ==12707== ==12707== This conflicts with a previous write of size 4 by thread #2 ==12707== Locks held: none ==12707== at 0x8050C4E: child_fn (in /export/home/windy/valgrind/race) ==12707== by 0x4FF889A6: mythread_wrapper (hg_intercepts.c:389) ==12707== by 0x4FF2683B: _thrp_setup (in /lib/libc.so.1) ==12707== by 0x4FF26ADF: ??? (in /lib/libc.so.1) ==12707== Address 0x8060f44 is 0 bytes inside data symbol "x" ==12707== ==12707== ---------------------------------------------------------------- ==12707== ==12707== Possible data race during write of size 4 at 0x8060F44 by thread #1 ==12707== Locks held: none ==12707== at 0x8050CE3: main (in /export/home/windy/valgrind/race) ==12707== ==12707== This conflicts with a previous write of size 4 by thread #2 ==12707== Locks held: none ==12707== at 0x8050C4E: child_fn (in /export/home/windy/valgrind/race) ==12707== by 0x4FF889A6: mythread_wrapper (hg_intercepts.c:389) ==12707== by 0x4FF2683B: _thrp_setup (in /lib/libc.so.1) ==12707== by 0x4FF26ADF: ??? (in /lib/libc.so.1) ==12707== Address 0x8060f44 is 0 bytes inside data symbol "x" ==12707== ==12707== ==12707== For counts of detected and suppressed errors, rerun with: -v ==12707== Use --history-level=approx or =none to gain increased speed, at ==12707== the cost of reduced accuracy of conflicting-access information ==12707== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0)
DRD는 쓰레드 오류 감지기다. POSIX pthread 를 사용하는 경우 Helgrind 보다 더 범용적으로 사용할 수 있다.
windy@wl ~/valgrind $ cc -o race ~/src/valgrind-3.15.0/helgrind/tests/tc01_simple_race.c windy@wl ~/valgrind $ valgrind --tool=drd ./race ==24465== drd, a thread error detector ==24465== Copyright (C) 2006-2017, and GNU GPL'd, by Bart Van Assche. ==24465== Using Valgrind-3.15.0 and LibVEX; rerun with -h for copyright info ==24465== Command: ./race ==24465== ==24465== Conflicting load by thread 1 at 0x08060f44 size 4 ==24465== at 0x8050CDB: main (in /export/home/windy/valgrind/race) ==24465== Allocation context: Data section of /export/home/windy/valgrind/race ==24465== Other segment start (thread 2) ==24465== (thread finished, call stack no longer available) ==24465== Other segment end (thread 2) ==24465== (thread finished, call stack no longer available) ==24465== ==24465== Conflicting store by thread 1 at 0x08060f44 size 4 ==24465== at 0x8050CE3: main (in /export/home/windy/valgrind/race) ==24465== Allocation context: Data section of /export/home/windy/valgrind/race ==24465== Other segment start (thread 2) ==24465== (thread finished, call stack no longer available) ==24465== Other segment end (thread 2) ==24465== (thread finished, call stack no longer available) ==24465== ==24465== ==24465== For counts of detected and suppressed errors, rerun with: -v ==24465== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0)
Massif 는 힙 프로파일러다. 툴을 실행시키면 massif.out 파일을 생성하며 ms_print(1)을 사용해 보면 된다.
windy@wl ~/valgrind $ wget https://www.solanara.net/contents/includes/valgrind_ms.c windy@wl ~/valgrind $ cc -o ms valgrind_ms.c windy@wl ~/valgrind $ valgrind --tool=massif --time-unit=B ./ms ==4421== Massif, a heap profiler ==4421== Copyright (C) 2003-2017, and GNU GPL'd, by Nicholas Nethercote ==4421== Using Valgrind-3.15.0 and LibVEX; rerun with -h for copyright info ==4421== Command: ./ms ==4421== ==4421== windy@wl ~/valgrind $ ms_print massif.out.4421 -------------------------------------------------------------------------------- Command: ./ms Massif arguments: --time-unit=B ms_print arguments: massif.out.4421 -------------------------------------------------------------------------------- KB 19.63^ ### | # | # :: | # : ::: | :::::::::# : : :: | : # : : : :: | : # : : : : ::: | : # : : : : : :: | ::::::::::: # : : : : : : ::: | : : # : : : : : : : :: | ::::: : # : : : : : : : : :: | @@@: : : # : : : : : : : : : @ | ::@ : : : # : : : : : : : : : @ | :::: @ : : : # : : : : : : : : : @ | ::: : @ : : : # : : : : : : : : : @ | ::: : : @ : : : # : : : : : : : : : @ | :::: : : : @ : : : # : : : : : : : : : @ | ::: : : : : @ : : : # : : : : : : : : : @ | :::: : : : : : @ : : : # : : : : : : : : : @ | ::: : : : : : : @ : : : # : : : : : : : : : @ 0 +----------------------------------------------------------------------->KB 0 29.48 Number of snapshots: 25 Detailed snapshots: [9, 14 (peak), 24] -------------------------------------------------------------------------------- n time(B) total(B) useful-heap(B) extra-heap(B) stacks(B) -------------------------------------------------------------------------------- 0 0 0 0 0 0 1 1,008 1,008 1,000 8 0 2 2,016 2,016 2,000 16 0 3 3,024 3,024 3,000 24 0 4 4,032 4,032 4,000 32 0 5 5,040 5,040 5,000 40 0 6 6,048 6,048 6,000 48 0 7 7,056 7,056 7,000 56 0 8 8,064 8,064 8,000 64 0 9 9,072 9,072 9,000 72 0 99.21% (9,000B) (heap allocation functions) malloc/new/new[], --alloc-fns, etc. ->99.21% (9,000B) 0x8050B9C: main (in /export/home/windy/valgrind/ms) -------------------------------------------------------------------------------- n time(B) total(B) useful-heap(B) extra-heap(B) stacks(B) -------------------------------------------------------------------------------- 10 10,080 10,080 10,000 80 0 11 12,088 12,088 12,000 88 0 12 16,096 16,096 16,000 96 0 13 20,104 20,104 20,000 104 0 14 20,104 20,104 20,000 104 0 99.48% (20,000B) (heap allocation functions) malloc/new/new[], --alloc-fns, etc. ->49.74% (10,000B) 0x8050B9C: main (in /export/home/windy/valgrind/ms) | ->39.79% (8,000B) 0x8050B51: g (in /export/home/windy/valgrind/ms) | ->19.90% (4,000B) 0x8050B79: f (in /export/home/windy/valgrind/ms) | | ->19.90% (4,000B) 0x8050BC0: main (in /export/home/windy/valgrind/ms) | | | ->19.90% (4,000B) 0x8050BC5: main (in /export/home/windy/valgrind/ms) | ->09.95% (2,000B) 0x8050B71: f (in /export/home/windy/valgrind/ms) ->09.95% (2,000B) 0x8050BC0: main (in /export/home/windy/valgrind/ms) -------------------------------------------------------------------------------- n time(B) total(B) useful-heap(B) extra-heap(B) stacks(B) -------------------------------------------------------------------------------- 15 21,112 19,096 19,000 96 0 16 22,120 18,088 18,000 88 0 17 23,128 17,080 17,000 80 0 18 24,136 16,072 16,000 72 0 19 25,144 15,064 15,000 64 0 20 26,152 14,056 14,000 56 0 21 27,160 13,048 13,000 48 0 22 28,168 12,040 12,000 40 0 23 29,176 11,032 11,000 32 0 24 30,184 10,024 10,000 24 0 99.76% (10,000B) (heap allocation functions) malloc/new/new[], --alloc-fns, etc. ->79.81% (8,000B) 0x8050B51: g (in /export/home/windy/valgrind/ms) | ->39.90% (4,000B) 0x8050B79: f (in /export/home/windy/valgrind/ms) | | ->39.90% (4,000B) 0x8050BC0: main (in /export/home/windy/valgrind/ms) | | | ->39.90% (4,000B) 0x8050BC5: main (in /export/home/windy/valgrind/ms) | ->19.95% (2,000B) 0x8050B71: f (in /export/home/windy/valgrind/ms) | ->19.95% (2,000B) 0x8050BC0: main (in /export/home/windy/valgrind/ms) | ->00.00% (0B) in 1+ places, all below ms_print's threshold (01.00%)
Massif 는 Execution Trees도 같이 제공한다. --xtree-memory
옵션을 붙여 실행한 후, xtmemory(1)을 사용해 분석하면 된다.
DHAT는 프로그램에서 할당된 힙을 어떻게 사용하고 있는지 분석해주는 툴이다.
windy@wl ~/valgrind $ valgrind --tool=exp-dhat ls ==9519== DHAT, a dynamic heap analysis tool ==9519== NOTE: This is an Experimental-Class Valgrind Tool ==9519== Copyright (C) 2010-2017, and GNU GPL'd, by Mozilla Inc ==9519== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info ==9519== Command: ls ==9519== ==9519== ==9519== ======== SUMMARY STATISTICS ======== ==9519== ==9519== guest_insns: 671,352 ==9519== ==9519== max_live: 44,815 in 8 blocks ==9519== ==9519== tot_alloc: 44,815 in 8 blocks ==9519== ==9519== insns per allocated byte: 14 ==9519== ==9519== ==9519== ======== ORDERED BY decreasing "max-bytes-live": top 10 allocators ======== ==9519== ==9519== -------------------- 1 of 10 -------------------- ==9519== max-live: 44,032 in 1 blocks ==9519== tot-alloc: 44,032 in 1 blocks (avg size 44032.00) ==9519== deaths: none (none of these blocks were freed) ==9519== acc-ratios: 0.00 rd, 0.00 wr (30 b-read, 226 b-written) ==9519== at 0xFFFF62717: malloc (vg_replace_malloc.c:311) ==9519== by 0x4053F6: main (in /usr/bin/ls) ==9519== ==9519== -------------------- 2 of 10 -------------------- ==9519== max-live: 512 in 1 blocks ==9519== tot-alloc: 512 in 1 blocks (avg size 512.00) ==9519== deaths: none (none of these blocks were freed) ==9519== acc-ratios: 0.03 rd, 0.01 wr (16 b-read, 8 b-written) ==9519== at 0xFFFF62717: malloc (vg_replace_malloc.c:311) ==9519== by 0x4053DA: main (in /usr/bin/ls) ==9519== ==9519== Aggregated access counts by offset: ==9519== ==9519== [ 0] 3 3 3 3 3 3 3 3 0 0 0 0 0 0 0 0 ==9519== [ 16] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ==9519== [ 32] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ==9519== [ 48] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ==9519== [ 64] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ==9519== [ 80] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ==9519== [ 96] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ==9519== [ 112] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ==9519== [ 128] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ==9519== [ 144] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ==9519== [ 160] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ==9519== [ 176] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ==9519== [ 192] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ==9519== [ 208] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ==9519== [ 224] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ==9519== [ 240] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ==9519== [ 256] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ==9519== [ 272] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ==9519== [ 288] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ==9519== [ 304] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ==9519== [ 320] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ==9519== [ 336] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ==9519== [ 352] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ==9519== [ 368] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ==9519== [ 384] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ==9519== [ 400] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ==9519== [ 416] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ==9519== [ 432] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ==9519== [ 448] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ==9519== [ 464] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ==9519== [ 480] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ==9519== [ 496] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ==9519== ==9519== -------------------- 3 of 10 -------------------- ==9519== max-live: 136 in 1 blocks ==9519== tot-alloc: 136 in 1 blocks (avg size 136.00) ==9519== deaths: none (none of these blocks were freed) ==9519== acc-ratios: 0.70 rd, 1.05 wr (96 b-read, 144 b-written) ==9519== at 0xFFFF62717: malloc (vg_replace_malloc.c:311) ==9519== by 0xFFFF16655: alloc_chain (in /lib/amd64/libc.so.1) ==9519== by 0xFFFF15E56: setlocale (in /lib/amd64/libc.so.1) ==9519== by 0x4045DC: main (in /usr/bin/ls) ==9519== ==9519== Aggregated access counts by offset: ==9519== ==9519== [ 0] 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 ==9519== [ 16] 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 ==9519== [ 32] 1 1 1 1 1 1 1 1 3 3 3 3 3 3 3 3 ==9519== [ 48] 2 2 2 2 2 2 2 2 3 3 3 3 3 3 3 3 ==9519== [ 64] 3 3 3 3 3 3 3 3 2 2 2 2 2 2 2 2 ==9519== [ 80] 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 ==9519== [ 96] 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 ==9519== [ 112] 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 ==9519== [ 128] 1 1 1 1 1 1 1 1 ==9519== ==9519== -------------------- 4 of 10 -------------------- ==9519== max-live: 48 in 1 blocks ==9519== tot-alloc: 48 in 1 blocks (avg size 48.00) ==9519== deaths: none (none of these blocks were freed) ==9519== acc-ratios: 0.50 rd, 1.41 wr (24 b-read, 68 b-written) ==9519== at 0xFFFF62717: malloc (vg_replace_malloc.c:311) ==9519== by 0xFFFF1828C: load_locale (in /lib/amd64/libc.so.1) ==9519== by 0xFFFF15E45: setlocale (in /lib/amd64/libc.so.1) ==9519== by 0x4045DC: main (in /usr/bin/ls) ==9519== ==9519== Aggregated access counts by offset: ==9519== ==9519== [ 0] 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 ==9519== [ 16] 1 1 1 1 1 1 1 1 13 13 13 13 0 0 0 0 ==9519== [ 32] 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 ==9519== ==9519== -------------------- 5 of 10 -------------------- ==9519== max-live: 48 in 1 blocks ==9519== tot-alloc: 48 in 1 blocks (avg size 48.00) ==9519== deaths: none (none of these blocks were freed) ==9519== acc-ratios: 0.33 rd, 0.33 wr (16 b-read, 16 b-written) ==9519== at 0xFFFF63790: calloc (vg_replace_malloc.c:722) ==9519== by 0xFFFEAFDF9: textdomain (in /lib/amd64/libc.so.1) ==9519== by 0x4045E8: main (in /usr/bin/ls) ==9519== ==9519== Aggregated access counts by offset: ==9519== ==9519== [ 0] 4 4 4 4 4 4 4 4 0 0 0 0 0 0 0 0 ==9519== [ 16] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ==9519== [ 32] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ==9519== ==9519== -------------------- 6 of 10 -------------------- ==9519== max-live: 15 in 1 blocks ==9519== tot-alloc: 15 in 1 blocks (avg size 15.00) ==9519== deaths: none (none of these blocks were freed) ==9519== acc-ratios: 2.13 rd, 1.06 wr (32 b-read, 16 b-written) ==9519== at 0xFFFF62717: malloc (vg_replace_malloc.c:311) ==9519== by 0xFFFEB2E06: _textdomain_u (in /lib/amd64/libc.so.1) ==9519== by 0xFFFEAFE1A: textdomain (in /lib/amd64/libc.so.1) ==9519== by 0x4045E8: main (in /usr/bin/ls) ==9519== ==9519== Aggregated access counts by offset: ==9519== ==9519== [ 0] 3 3 3 3 3 3 3 5 3 3 3 3 3 3 3 ==9519== ==9519== -------------------- 7 of 10 -------------------- ==9519== max-live: 12 in 1 blocks ==9519== tot-alloc: 12 in 1 blocks (avg size 12.00) ==9519== deaths: none (none of these blocks were freed) ==9519== acc-ratios: 9.66 rd, 1.00 wr (116 b-read, 12 b-written) ==9519== at 0xFFFF62717: malloc (vg_replace_malloc.c:311) ==9519== by 0xFFFEA68C9: strdup (in /lib/amd64/libc.so.1) ==9519== by 0xFFFF17A3D: expand_locale_name (in /lib/amd64/libc.so.1) ==9519== by 0xFFFF15DD8: setlocale (in /lib/amd64/libc.so.1) ==9519== by 0x4045DC: main (in /usr/bin/ls) ==9519== ==9519== Aggregated access counts by offset: ==9519== ==9519== [ 0] 10 9 9 9 9 9 9 9 9 9 9 8 ==9519== ==9519== -------------------- 8 of 10 -------------------- ==9519== max-live: 12 in 1 blocks ==9519== tot-alloc: 12 in 1 blocks (avg size 12.00) ==9519== deaths: none (none of these blocks were freed) ==9519== acc-ratios: 0.00 rd, 1.00 wr (0 b-read, 12 b-written) ==9519== at 0xFFFF62717: malloc (vg_replace_malloc.c:311) ==9519== by 0xFFFEA68C9: strdup (in /lib/amd64/libc.so.1) ==9519== by 0xFFFF182A4: load_locale (in /lib/amd64/libc.so.1) ==9519== by 0xFFFF15E45: setlocale (in /lib/amd64/libc.so.1) ==9519== by 0x4045DC: main (in /usr/bin/ls) ==9519== ==9519== Aggregated access counts by offset: ==9519== ==9519== [ 0] 1 1 1 1 1 1 1 1 1 1 1 1 ==9519== ==9519== ==9519== ==9519== ============================================================== ==9519== ==9519== Some hints: (see --help for command line option details): ==9519== ==9519== * summary stats for whole program are at the top of this output ==9519== ==9519== * --show-top-n= controls how many alloc points are shown. ==9519== You probably want to set it much higher than ==9519== the default value (10) ==9519== ==9519== * --sort-by= specifies the sort key for output. ==9519== See --help for details. ==9519== ==9519== * Each allocation stack, by default 12 frames, counts as ==9519== a separate alloc point. This causes the data to be spread out ==9519== over far too many alloc points. I strongly suggest using ==9519== --num-callers=4 or some such, to reduce the spreading. ==9519==
BBV는 기본블록(Basic Block, 한개의 입구와 한개의 출구로 이뤄지며 중간에 점프하는 구문이 없는 블록)이 실행되는 회수를 확인해준다. 실험적인 기능이다.
windy@wl ~/valgrind $ valgrind --tool=exp-bbv /bin/ls ==11559== exp-bbv, a SimPoint basic block vector generator ==11559== NOTE: This is an Experimental-Class Valgrind Tool ==11559== Copyright (C) 2006-2017 Vince Weaver ==11559== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info ==11559== Command: /bin/ls ==11559== ==11559== ==11559== ==11559== ==11559== # Thread 1 ==11559== # Total intervals: 0 (Interval Size 100000000) ==11559== # Total instructions: 614608 ==11559== # Total reps: 1292 ==11559== # Unique reps: 1 ==11559== # Total fldcw instructions: 0 ==11559== ==11559==
valgrind-di-server(1) 는 Valgrind 의 디버그 정보를 수신할 수 있는 서버다. valgrind 를 실행할 때, --debuginfo-server=ipaddr:port
옵션을 붙여 디버그 정보를 전송할 수 있다. 실험적인 기능이다.
vgdb 는 Valgrind 와 GDB 또는 셸을 이어주는 툴이다.
RSS ATOM XHTML 5 CSS3 |
Copyright © 2004-2024 Jo HoSeok. All rights reserved. |