4、内存泄漏多线程
多线程下使用Valgrind
工具的memcheck
检查.
安装
shell
sudo apt install valgrind
使用
sh
valgrind --tool=memcheck --leak-check=full ./app_main
指令效果如下所示.
sh
wq@wq-Virtual-Machine:~/work/test_zlog/build$ valgrind --tool=memcheck --leak-check=full ./app_main
==89377== Memcheck, a memory error detector
==89377== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==89377== Using Valgrind-3.15.0 and LibVEX; rerun with -h for copyright info
==89377== Command: ./app_main
==89377==
==89377==
==89377== HEAP SUMMARY:
==89377== in use at exit: 1,512 bytes in 2 blocks
==89377== total heap usage: 7 allocs, 5 frees, 2,440 bytes allocated
==89377==
==89377== 512 bytes in 1 blocks are definitely lost in loss record 1 of 2
==89377== at 0x483B7F3: malloc (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==89377== by 0x48F7228: mtrace (mtrace.c:326)
==89377== by 0x4011E5: main (main.c:13)
==89377==
==89377== 1,000 bytes in 1 blocks are definitely lost in loss record 2 of 2
==89377== at 0x483B7F3: malloc (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==89377== by 0x401209: main (main.c:19)
==89377==
==89377== LEAK SUMMARY:
==89377== definitely lost: 1,512 bytes in 2 blocks
==89377== indirectly lost: 0 bytes in 0 blocks
==89377== possibly lost: 0 bytes in 0 blocks
==89377== still reachable: 0 bytes in 0 blocks
==89377== suppressed: 0 bytes in 0 blocks
==89377==
==89377== For lists of detected and suppressed errors, rerun with: -s
==89377== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0)
shell
valgrind --tool=memcheck --leak-check=full --show-leak-kinds=all --log-file=out.txt ./app_main
该指令详细说明见下文,该指令输出内容会被保存到与可执行文件统计目录下的out.txt
文件中.
命令详解
通用命令
basic user options for all Valgrind tools, with defaults in [ ]:
-h --help show this message
--help-debug show this message, plus debugging options
--version show version
-q --quiet run silently; only print error msgs
-v --verbose be more verbose -- show misc extra info
--trace-children=no|yes Valgrind-ise child processes (follow execve)? [no]
--trace-children-skip=patt1,patt2,... specifies a list of executables
that --trace-children=yes should not trace into
--trace-children-skip-by-arg=patt1,patt2,... same as --trace-children-skip=
but check the argv[] entries for children, rather
than the exe name, to make a follow/no-follow decision
--child-silent-after-fork=no|yes omit child output between fork & exec? [no]
--vgdb=no|yes|full activate gdbserver? [yes]
full is slower but provides precise watchpoint/step
--vgdb-error=<number> invoke gdbserver after <number> errors [999999999]
to get started quickly, use --vgdb-error=0
and follow the on-screen directions
--vgdb-stop-at=event1,event2,... invoke gdbserver for given events [none]
where event is one of:
startup exit valgrindabexit all none
--track-fds=no|yes track open file descriptors? [no]
--time-stamp=no|yes add timestamps to log messages? [no]
--log-fd=<number> log messages to file descriptor [2=stderr]
--log-file=<file> log messages to <file>
--log-socket=ipaddr:port log messages to socket ipaddr:port
user options for Memcheck:
--leak-check=no|summary|full search for memory leaks at exit? [summary]
--leak-resolution=low|med|high differentiation of leak stack traces [high]
--show-leak-kinds=kind1,kind2,.. which leak kinds to show?
[definite,possible]
--errors-for-leak-kinds=kind1,kind2,.. which leak kinds are errors?
[definite,possible]
where kind is one of:
definite indirect possible reachable all none
--leak-check-heuristics=heur1,heur2,... which heuristics to use for
improving leak search false positive [all]
where heur is one of:
stdstring length64 newarray multipleinheritance all none
--show-reachable=yes same as --show-leak-kinds=all
--show-reachable=no --show-possibly-lost=yes
same as --show-leak-kinds=definite,possible
--show-reachable=no --show-possibly-lost=no
same as --show-leak-kinds=definite
--xtree-leak=no|yes output leak result in xtree format? [no]
--xtree-leak-file=<file> xtree leak report file [xtleak.kcg.%p]
--undef-value-errors=no|yes check for undefined value errors [yes]
--track-origins=no|yes show origins of undefined values? [no]
--partial-loads-ok=no|yes too hard to explain here; see manual [yes]
--expensive-definedness-checks=no|auto|yes
Use extra-precise definedness tracking [auto]
--freelist-vol=<number> volume of freed blocks queue [20000000]
--freelist-big-blocks=<number> releases first blocks with size>= [1000000]
--workaround-gcc296-bugs=no|yes self explanatory [no]. Deprecated.
Use --ignore-range-below-sp instead.
--ignore-ranges=0xPP-0xQQ[,0xRR-0xSS] assume given addresses are OK
--ignore-range-below-sp=<number>-<number> do not report errors for
accesses at the given offsets below SP
--malloc-fill=<hexnumber> fill malloc'd areas with given value
--free-fill=<hexnumber> fill free'd areas with given value
--keep-stacktraces=alloc|free|alloc-and-free|alloc-then-free|none
stack trace(s) to keep for malloc'd/free'd areas [alloc-and-free]
--show-mismatched-frees=no|yes show frees that don't match the allocator? [yes]
下列命令可跟在valgrind
后面.
--tool=memcheck
- 使用memcheck工具,有很多工具很选,例如,
Memcheck,
Addrcheck
,Cachegrind,
等等。
- 使用memcheck工具,有很多工具很选,例如,
--leak-check=full
- 要求对leak给出详细信息
--log-file=output.txt
- 将分析信息输出值
output.txt
文件
- 将分析信息输出值
--show-leak-kinds=all
- 显示所有类型的内存泄漏,包括
"definitely lost"
、"indirectly lost"
、"possibly lost"
和"still reachable"
。
- 显示所有类型的内存泄漏,包括
输出详解
valgrind输出结果会报告5种内存泄露.
-
"definitely lost"
:确认丢失。程序中存在内存泄露,应尽快修复。当程序结束时如果一块动态分配的内存没有被释放且通过程序内的指针变量均无法访问这块内存则会报这个错误。 -
"indirectly lost"
:间接丢失。当使用了含有指针成员的类或结构时可能会报这个错误。这类错误无需直接修复,他们总是与"definitely lost"一起出现,只要修复"definitely lost"即可。- 这表示没有间接丢失的内存。间接丢失的内存是指,由于直接丢失的内存块包含了指向这些内存的指针,因此这些内存也被视为丢失。
-
"possibly lost"
:可能丢失。大多数情况下应视为与"definitely lost"一样需要尽快修复,除非你的程序让一个指针指向一块动态分配的内存(但不是这块内存起始地址),然后通过运算得到这块内存起始地址,再释放它。例子可参考我的例程。当程序结束时如果一块动态分配的内存没有被释放且通过程序内的指针变量均无法访问这块内存的起始地址,但可以访问其中的某一部分数据,则会报这个错误。 -
"still reachable"
:可以访问,未丢失但也未释放。如果程序是正常结束的,那么它可能不会造成程序崩溃,但长时间运行有可能耗尽系统资源,因此笔者建议修复它。如果程序是崩溃(如访问非法的地址而崩溃)而非正常结束的,则应当暂时忽略它,先修复导致程序崩溃的错误,然后重新检测。 -
"suppressed"
:已被解决。出现了内存泄露但系统自动处理了。可以无视这类错误。
附录1 tool初步认识
- Memcheck是一个内存错误检测器。它有助于使你的程序,尤其是那些用C和C++写的程序,更加准确。
- Cachegrind是一个缓存和分支预测分析器。它有助于使你的程序运行更快。
- Callgrind是一个调用图缓存生成分析器。它与Cachegrind的功能有重叠,但也收集Cachegrind不收集的一些信息。
- Helgrind是一个线程错误检测器。它有助于使你的多线程程序更加准确。
- DRD也是一个线程错误检测器。它和Helgrind相似,但使用不同的分析技术,所以可能找到不同的问题。
- Massif是一个堆分析器。它有助于使你的程序使用更少的内存。
- DHAT是另一种不同的堆分析器。它有助于理解块的生命期、块的使用和布局的低效等问题。
- SGcheck是一个实验工具,用来检测堆和全局数组的溢出。它的功能和Memcheck互补:SGcheck找到Memcheck无法找到的问题,反之亦然。
- BBV是个实验性质的SimPoint基本块矢量生成器。它对于进行计算机架构的研究和开发很有用处。