使用valgrind分析C程序内存泄露
Valgrind简介
使用格式:
valgrind [options] prog-and-args
基本工具介绍
Memcheck 这是valgrind应用最广泛的工具,一个重量级的内存检查器,能够发现开发中绝大多数内存错误使用情况,比如:使用未初始化的内存,未释放的内存,使用已经释放了的内存,内存访问越界等。
Callgrind 它主要用来检查程序中函数调用过程中出现的问题。
Cachegrind 它主要用来检查程序中缓存使用出现的问题。
Helgrind 它主要用来检查多线程程序中出现的竞争问题。
Massif 它主要用来检查程序中堆栈使用中出现的问题。
Extension 可以利用core提供的功能,自己编写特定的内存调试工具
Memcheck工具介绍
Memcheck是valgrind应用最广泛的工具,能够发现开发中绝大多数内存错误使用情况。此工具主要可检查以下错误:
(1) 使用未初始化的内存(Use of uninitialised memory)
(2) 使用已经释放了的内存(Reading/writing memory after it has been free’d)
(3) 使用超过malloc分配的内存空间(Reading/writing off the end of malloc’d blocks)
(4) 对堆栈的非法访问(Reading/writing inappropriate areas on the stack)
(5) 申请的空间是否有释放(Memory leaks – where pointers to malloc’d blocks are lost forever)
(6) malloc/free/new/delete申请和释放内存的匹配(Mismatched use of malloc/new/new [] vs free/delete/delete [])
(7) src和dst的重叠(Overlapping src and dst pointers in memcpy() and related functions)
options选项:
- –tool= 运行 valgrind中名为toolname的工具。例如memcheck(默认),cachegrind,callgrind,helgrind,drd,massif,dhat,bouchey,none,exp-bbv等。
- -h –help 显示帮助信息。
- –version 显示valgrind内核的版本,每个工具都有各自的版本。
- -q –quiet 安静地运行,只打印错误信息。
- -v –verbose 更详细的信息, 增加错误数统计。
- –trace-children=no|yes 跟踪子线程? [no]
- –track-fds=no|yes 跟踪打开的文件描述?[no]
- –time-stamp=no|yes 增加时间戳到LOG信息? [no]
- –log-fd= 输出LOG到描述符文件 [2=stderr]
- –log-file= 将输出LOG信息写入到指定文件里
- –log-file-exactly= 输出LOG信息到 file
- –log-file-qualifier= 取得环境变量的值来做为输出信息的文件名。 [none]
- –log-socket= 输出LOG信息到指定IP地址的指定端口
valgrind --tool=memcheck \
--leak-check=full \
--log-file=/huanuo/log ./hn_product_strip
可在终端所在文件夹下生成log文件,在log文件最后会有个summary,其中对内存泄露进行了分类,总共有五类:
definitely lost意味着你的程序一定存在内存泄露;
indirectly lost意味着你的程序一定存在内存泄露,并且泄露情况和指针结构相关
possibly lost意味着你的程序一定存在内存泄露,除非你是故意进行着不符合常规的操作,例如将指针指向某个已分配内存块的中间位置。
still reachable意味着你的程序可能是没问题的,但确实没有释放掉一些本可以释放的内存。这种情况是很常见的,并且通常基于合理的理由。
suppressed意味着有些泄露信息被压制了。在默认的 suppression 文件中可以看到一些 suppression 相关设置。
生成的日志
==8451== 115,245 bytes in 40 blocks are definitely lost in loss record 19 of 19
==8451== at 0x485114C: realloc (in /sdcard/valgrind/libexec/valgrind/vgpreload_memcheck-arm64-linux.so)
==8451== by 0x58F653: print (cJSON.c:1226)
==8451== by 0x58F76B: cJSON_Print (cJSON.c:1268)
==8451== by 0x45ED23: response_success (common_action.c:26)
==8451== by 0x440AC3: callApi (goahead_serv.c:244)
==8451== by 0x440C23: callHuanuoApi (goahead_serv.c:281)
==8451== by 0x44FF9B: actionHandler (action.c:56)
==8451== by 0x43384B: websRunRequest (route.c:182)
==8451== by 0x429ADB: websPump (http.c:865)
==8451== by 0x42995F: readEvent (http.c:829)
==8451== by 0x4296FB: socketEvent (http.c:767)
==8451== by 0x43CD1F: socketDoEvent (socket.c:654)
==8451==
==8451== LEAK SUMMARY:
==8451== definitely lost: 119,174 bytes in 64 blocks
==8451== indirectly lost: 0 bytes in 0 blocks
==8451== possibly lost: 544 bytes in 2 blocks
==8451== still reachable: 3,293 bytes in 31 blocks
==8451== suppressed: 0 bytes in 0 blocks
==8451== Reachable blocks (those to which a pointer was found) are not shown.
==8451== To see them, rerun with: --leak-check=full --show-leak-kinds=all
==8451==
==8451== Use --track-origins=yes to see where uninitialised values come from
==8451== For lists of detected and suppressed errors, rerun with: -s
==8451== ERROR SUMMARY: 345464 errors from 145 contexts (suppressed: 0 from 0)
这样的是一个错误,先告诉你出现了多少的内存泄露,然后从最里层不断往外部函数显示:先说是calloc造成的错误,然后不断往外部函数显示。