javascript内存泄漏调试工具mac_内存泄漏检测工具valgrind神器

1概述

1.1 介绍

Valgrind是一套Linux下,开放源代码(GPL V2)的仿真调试工具的集合。Valgrind由内核(core)以及基于内核的其他调试工具组成。内核类似于一个框架(framework),它模拟了一个CPU环境,并提供服务给其他工具;而其他工具则类似于插件 (plug-in),利用内核提供的服务完成各种特定的内存调试任务。Valgrind的体系结构如下图所示:

5541bcfc8c03f69d9e295a9cae8f242a.png

图1

1.2 工具

Valgrind的最新版是3.11.0,它一般包含下列工具:

1.Memcheck

最常用的工具,用来检测程序中出现的内存问题,所有对内存的读写都会被检测到,一切对malloc()/free()/new/delete的调用都会被捕获。所以,它能检测以下问题:

对未初始化内存的使用;

读/写释放后的内存块;

读/写超出malloc分配的内存块;

读/写不适当的栈中内存块;

内存泄漏,指向一块内存的指针永远丢失;

不正确的malloc/free或new/delete匹配;

memcpy()相关函数中的dst和src指针重叠。

2.Callgrind

和gprof类似的分析工具,但它对程序的运行观察更是入微,能给我们提供更多的信息。和gprof不同,它不需要在编译源代码时附加特殊选项,但加上调试选项是推荐的。Callgrind收集程序运行时的一些数据,建立函数调用关系图,还可以有选择地进行cache模拟。在运行结束时,它会把分析数据写入一个文件。callgrind_annotate可以把这个文件的内容转化成可读的形式。

3.Cachegrind

Cache分析器,它模拟CPU中的一级缓存I1,Dl和二级缓存,能够精确地指出程序中cache的丢失和命中。如果需要,它还能够为我们提供cache丢失次数,内存引用次数,以及每行代码,每个函数,每个模块,整个程序产生的指令数。这对优化程序有很大的帮助。

4.Helgrind

它主要用来检查多线程程序中出现的竞争问题。Helgrind寻找内存中被多个线程访问,而又没有一贯加锁的区域,这些区域往往是线程之间失去同步的地方,而且会导致难以发掘的错误。Helgrind实现了名为“Eraser”的竞争检测算法,并做了进一步改进,减少了报告错误的次数。不过,Helgrind仍然处于实验阶段。

5.Massif

堆栈分析器,它能测量程序在堆栈中使用了多少内存,告诉我们堆块,堆管理块和栈的大小。Massif能帮助我们减少内存的使用,在带有虚拟内存的现代系统中,它还能够加速我们程序的运行,减少程序停留在交换区中的几率。

此外,lackey和nulgrind也会提供。Lackey是小型工具,很少用到;Nulgrind只是为开发者展示如何创建一个工具。

1.3 原理

Memcheck 能够检测出内存问题,关键在于其建立了两个全局表。Valid-Value 表

对于进程的整个地址空间中的每一个字节(byte),都有与之对应的 8 个 bits;对于CPU的每个寄存器,也有一个与之对应的bit向量。这些bits负责记录该字节或者寄存器值是否具有有效的、已初始化的值。

Valid-Address 表

对于进程整个地址空间中的每一个字节(byte),还有与之对应的1个bit,负责记录该地址是否能够被读写。

检测原理:

当要读写内存中某个字节时,首先检查这个字节对应的 A bit。如果该A bit显示该位置是无效位置,memcheck则报告读写错误。

内核(core)类似于一个虚拟的 CPU 环境,这样当内存中的某个字节被加载到真实的 CPU 中时,该字节对应的 V bit 也被加载到虚拟的 CPU 环境中。一旦寄存器中的值,被用来产生内存地址,或者该值能够影响程序输出,则 memcheck 会检查对应的V bits,如果该值尚未初始化,则会报告使用未初始化内存错误。

2 安装使用

2.1安装

从官网http://www.valgrind.org下载最新版本(当前3.11)

#tar xvf valgrind-3.11.1.tar.bz2

#cd valgrind-3.11.1

#./configure --prefix=/usr/local/valgrind--指定安装目录

#make

#make install

2.2 命令介绍

用法:valgrind[options] prog-and-args [options]: 常用选项,适用于所有Valgrind工具

-tool= 最常用的选项。运行 valgrind中名为toolname的工具。默认memcheck。

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= 将输出的信息写入到filename.PID的文件里,PID是运行程序的进行ID

-log-file-exactly= 输出LOG信息到 file

-log-file-qualifier= 取得环境变量的值来做为输出信息的文件名。 [none]

-log-socket=ipaddr:port 输出LOG到socket ,ipaddr:port

LOG信息输出:

-xml=yes 将信息以xml格式输出,只有memcheck可用

-num-callers= show callers in stack traces [12]

-error-limit=no|yes 如果太多错误,则停止显示新错误? [yes]

-error-exitcode= 如果发现错误则返回错误代码 [0=disable]

-db-attach=no|yes 当出现错误,valgrind会自动启动调试器gdb。[no]

-db-command= 启动调试器的命令行选项[gdb -nw %f %p]

适用于Memcheck工具的相关选项:

-leak-check=no|summary|full 要求对leak给出详细信息? [summary]

-leak-resolution=low|med|high how much bt merging in leak check [low]

-show-reachable=no|yes show reachable blocks in leak check? [no]

3 应用实践

下面通过介绍几个范例来说明如何使用Memcheck (其他工具暂不涉及,感兴趣可以交流),示例仅供参考,更多用途可在实际应用中不断探索。

3.1数组越界/内存未释放

#include

void k(void)

{

int *x = malloc(8 * sizeof(int));

x[9] = 0; //数组下标越界

} //内存未释放

int main(void)

{

k();

return 0;

}

1)编译程序test.c

gcc -Wall test.c -g -o test#Wall提示所有告警,-g gdb,-o输出

2)使用Valgrind检查程序BUG

valgrind --tool=memcheck --leak-check=full ./test

#--leak-check=full 所有泄露检查

3) 运行结果如下:

==2989== Memcheck, a memory error detector

==2989== Copyright (C) 2002-2012, and GNU GPL'd, by Julian Seward

et al.

==2989== Using Valgrind-3.8.1 and LibVEX; rerun with -h for

copyright info

==2989== Command: ./test

==2989==

==2989== Invalid write of size 4

==2989== at 0x4004E2: k (test.c:5)

==2989== by 0x4004F2: main (test.c:10)

==2989== Address 0x4c27064 is 4 bytes after a block of size 32 alloc'd

==2989== at 0x4A06A2E: malloc (vg_replace_malloc.c:270)

==2989== by 0x4004D5: k (test.c:4)

==2989== by 0x4004F2: main (test.c:10)

==2989==

==2989==

==2989== HEAP SUMMARY:

==2989== in use at exit: 32 bytes in 1 blocks

==2989== total heap usage: 1 allocs, 0 frees, 32 bytes allocated

==2989==

==2989== 32 bytes in 1 blocks are definitely lost in loss record 1

of 1

==2989== at 0x4A06A2E: malloc (vg_replace_malloc.c:270)

==2989== by 0x4004D5: k (test.c:4)

==2989== by 0x4004F2: main (test.c:10)

==2989==

==2989== LEAK SUMMARY:

==2989== definitely lost: 32 bytes in 1 blocks

==2989== indirectly lost: 0 bytes in 0 blocks

==2989== possibly lost: 0 bytes in 0 blocks

==2989== still reachable: 0 bytes in 0 blocks

==2989==suppressed: 0 bytes in 0 blocks

==2989==

==2989== For counts of detected and suppressed errors, rerun with: -v

==2989== ERROR SUMMARY: 2 errors from 2 contexts

(suppressed: 6 from 6)

3.2内存释放后读写

#include

#include

int main(void)

{

char *p = malloc(1); //分配

*p = 'a';

char c = *p;

printf(" [%c]

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值