自動メモリリークチェッカーの調査
この回答では、簡単に理解できるメモリリークの例で、いくつかの異なるメモリリークチェッカーを比較します。
何よりもまず、人に知られているすべてのツールを比較するASan wikiの次の巨大なテーブルを参照してください:https : //github.com/google/sanitizers/wiki/AddressSanitizerComparisonOfMemoryTools/d06210f759fec97066888e5f27c7e722832b0924
分析される例は次のとおりです。
main.c
#include <stdlib.h>
void * my_malloc(size_t n) {
return malloc(n);
}
void leaky(size_t n, int do_leak) {
void *p = my_malloc(n);
if (!do_leak) {
free(p);
}
}
int main(void) {
leaky(0x10, 0);
leaky(0x10, 1);
leaky(0x100, 0);
leaky(0x100, 1);
leaky(0x1000, 0);
leaky(0x1000, 1);
}
GitHubアップストリーム。
さまざまなツールがどのようにリークのある呼び出しを示しているかを確認します。
Googleのgperftoolsのtcmalloc
https://github.com/gperftools/gperftools
Ubuntu 19.04での使用:
sudo apt-get install google-perftools
gcc -ggdb3 -o main.out main.c -ltcmalloc
PPROF_PATH=/usr/bin/google-pprof \
HEAPCHECK=normal \
HEAPPROFILE=ble \
./main.out \
;
google-pprof main.out ble.0001.heap --text
プログラム実行の出力には、メモリリーク分析が含まれています。
WARNING: Perftools heap leak checker is active -- Performance may suffer
Starting tracking the heap
Dumping heap profile to ble.0001.heap (Exiting, 4 kB in use)
Have memory regions w/o callers: might report false leaks
Leak check _main_ detected leaks of 272 bytes in 2 objects
The 2 largest leaks:
Using local file ./main.out.
Leak of 256 bytes in 1 objects allocated from:
@ 555bf6e5815d my_malloc
@ 555bf6e5817a leaky
@ 555bf6e581d3 main
@ 7f71e88c9b6b __libc_start_main
@ 555bf6e5808a _start
Leak of 16 bytes in 1 objects allocated from:
@ 555bf6e5815d my_malloc
@ 555bf6e5817a leaky
@ 555bf6e581b5 main
@ 7f71e88c9b6b __libc_start_main
@ 555bf6e5808a _start
If the preceding stack traces are not enough to find the leaks, try running THIS shell command:
pprof ./main.out "/tmp/main.out.24744._main_-end.heap" --inuse_objects --lines --heapcheck --edgefraction=1e-10 --nodefraction=1e-10 --gv
If you are still puzzled about why the leaks are there, try rerunning this program with HEAP_CHECK_TEST_POINTER_ALIGNMENT=1 and/or with HEAP_CHECK_MAX_POINTER_OFFSET=-1
If the leak report occurs in a small fraction of runs, try running with TCMALLOC_MAX_FREE_QUEUE_SIZE of few hundred MB or with TCMALLOC_RECLAIM_MEMORY=false, it might help find leaks more re
Exiting with error code (instead of crashing) because of whole-program memory leaks
の出力にgoogle-pprof
は、ヒープ使用量分析が含まれています。
Using local file main.out.
Using local file ble.0001.heap.
Total: 0.0 MB
0.0 100.0% 100.0% 0.0 100.0% my_malloc
0.0 0.0% 100.0% 0.0 100.0% __libc_start_main
0.0 0.0% 100.0% 0.0 100.0% _start
0.0 0.0% 100.0% 0.0 100.0% leaky
0.0 0.0% 100.0% 0.0 100.0% main
出力は、3つのリークのうち2つを示しています。
Leak of 256 bytes in 1 objects allocated from:
@ 555bf6e5815d my_malloc
@ 555bf6e5817a leaky
@ 555bf6e581d3 main
@ 7f71e88c9b6b __libc_start_main
@ 555bf6e5808a _start
Leak of 16 bytes in 1 objects allocated from:
@ 555bf6e5815d my_malloc
@ 555bf6e5817a leaky
@ 555bf6e581b5 main
@ 7f71e88c9b6b __libc_start_main
@ 555bf6e5808a _start
3つ目が表示されなかった理由がわかりません
いずれにせよ、通常何かが漏れるとき、それは何度も起こり、実際のプロジェクトでそれを使用したとき、漏れている関数を非常に簡単に指摘されてしまいました。
出力自体で述べたように、これにより実行速度が大幅に低下します。
さらなるドキュメント:
参照:TCMallocの使用方法
Ubuntu 19.04、google-perftools 2.5-2でテスト済み。
GoogleによるAddress Sanitizer(ASan)も
https://github.com/google/sanitizers
以前に言及:C ++コード/プロジェクトでメモリリークを見つける方法?TODO vs tcmalloc。
これはすでにGCCに統合されているので、次のことができます。
gcc -fsanitize=address -ggdb3 -o main.out main.c
./main.out
および実行出力:
=================================================================
==27223==ERROR: LeakSanitizer: detected memory leaks
Direct leak of 4096 byte(s) in 1 object(s) allocated from:
#0 0x7fabbefc5448 in malloc (/usr/lib/x86_64-linux-gnu/libasan.so.5+0x10c448)
#1 0x55bf86c5f17c in my_malloc /home/ciro/test/main.c:4
#2 0x55bf86c5f199 in leaky /home/ciro/test/main.c:8
#3 0x55bf86c5f210 in main /home/ciro/test/main.c:20
#4 0x7fabbecf4b6a in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x26b6a)
Direct leak of 256 byte(s) in 1 object(s) allocated from:
#0 0x7fabbefc5448 in malloc (/usr/lib/x86_64-linux-gnu/libasan.so.5+0x10c448)
#1 0x55bf86c5f17c in my_malloc /home/ciro/test/main.c:4
#2 0x55bf86c5f199 in leaky /home/ciro/test/main.c:8
#3 0x55bf86c5f1f2 in main /home/ciro/test/main.c:18
#4 0x7fabbecf4b6a in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x26b6a)
Direct leak of 16 byte(s) in 1 object(s) allocated from:
#0 0x7fabbefc5448 in malloc (/usr/lib/x86_64-linux-gnu/libasan.so.5+0x10c448)
#1 0x55bf86c5f17c in my_malloc /home/ciro/test/main.c:4
#2 0x55bf86c5f199 in leaky /home/ciro/test/main.c:8
#3 0x55bf86c5f1d4 in main /home/ciro/test/main.c:16
#4 0x7fabbecf4b6a in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x26b6a)
SUMMARY: AddressSanitizer: 4368 byte(s) leaked in 3 allocation(s).
すべてのリークを明確に識別します。いいね!
牙山はまた、このような範囲外の書き込みなどの他のクールなチェックを行うことができますスタックが検出スマッシング
Ubuntu 19.04、GCC 8.3.0でテスト済み。
ヴァルグリンド
http://www.valgrind.org/
以前に言及:https : //stackoverflow.com/a/37661630/895245
使用法:
sudo apt-get install valgrind
gcc -ggdb3 -o main.out main.c
valgrind --leak-check=yes ./main.out
出力:
==32178== Memcheck, a memory error detector
==32178== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==32178== Using Valgrind-3.14.0 and LibVEX; rerun with -h for copyright info
==32178== Command: ./main.out
==32178==
==32178==
==32178== HEAP SUMMARY:
==32178== in use at exit: 4,368 bytes in 3 blocks
==32178== total heap usage: 6 allocs, 3 frees, 8,736 bytes allocated
==32178==
==32178== 16 bytes in 1 blocks are definitely lost in loss record 1 of 3
==32178== at 0x483874F: malloc (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==32178== by 0x10915C: my_malloc (main.c:4)
==32178== by 0x109179: leaky (main.c:8)
==32178== by 0x1091B4: main (main.c:16)
==32178==
==32178== 256 bytes in 1 blocks are definitely lost in loss record 2 of 3
==32178== at 0x483874F: malloc (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==32178== by 0x10915C: my_malloc (main.c:4)
==32178== by 0x109179: leaky (main.c:8)
==32178== by 0x1091D2: main (main.c:18)
==32178==
==32178== 4,096 bytes in 1 blocks are definitely lost in loss record 3 of 3
==32178== at 0x483874F: malloc (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==32178== by 0x10915C: my_malloc (main.c:4)
==32178== by 0x109179: leaky (main.c:8)
==32178== by 0x1091F0: main (main.c:20)
==32178==
==32178== LEAK SUMMARY:
==32178== definitely lost: 4,368 bytes in 3 blocks
==32178== indirectly lost: 0 bytes in 0 blocks
==32178== possibly lost: 0 bytes in 0 blocks
==32178== still reachable: 0 bytes in 0 blocks
==32178== suppressed: 0 bytes in 0 blocks
==32178==
==32178== For counts of detected and suppressed errors, rerun with: -v
==32178== ERROR SUMMARY: 3 errors from 3 contexts (suppressed: 0 from 0)
したがって、もう一度、すべてのリークが検出されました。
参照:valgrindを使用してメモリリークを見つけるにはどうすればよいですか?
Ubuntu 19.04、valgrind 3.14.0でテスト済み。