瓦尔格隆德
本文只是对memcheck进行学习
学习资料:
官网主页: http://valgrind.org/
Valgrind用户手册 : http://valgrind.org/docs/manual/manual.html
CSDN 博文 :
https://blog.csdn.net/andylauren/article/details/93189740
https://blog.csdn.net/u010122972/article/details/78214174
Valgrind是GPL的系统,用于调试和分析Linux程序。
内存检查
Memcheck可检测内存管理问题,并且主要针对C和C++程序。在Memcheck的监视下运行程序时,将检查所有内存读取和写入,并拦截对malloc / new / free / delete的调用。
重叠src和 dst指针 memcpy以及相关功能。
Memcheck会在发生这些错误时立即报告这些错误,并给出发生错误的源代码行号,以及为达到该行而调用的函数的堆栈跟踪。
Cachegrind是一个缓存分析器。它可以对CPU中的I1,D1和L2缓存进行详细的仿真,因此可以准确地指出代码中的缓存未命中源。
它提供了Cachegrind所做的所有信息,以及有关调用图的其他信息。
Massif是堆分析器。包括有关程序的哪些部分负责最多内存分配的信息。
Helgrind是一个线程调试器,可在多线程程序中查找数据竞争。
http://valgrind.org/docs/manual/QuickStart.html
用户文档: http://valgrind.org/docs/manual/manual-core.html
安装包网址 : http://www.valgrind.org/downloads/current.html
或者
git clone git://sourceware.org/git/valgrind.git
下载源码、下载文档
tar jxvf valgrind-3.15.0.tar.bz2
cd valgrind-3.15.0/
./configure
make
make install
//验证是否安装成功
valgrind --version
#include
#include
#include
int main(int argc, char *argv[]){
// int x = 1;
int x;
printf("x [%d]\n\n", x); //1、使用未初始化的变量
char * str1 = malloc(10); //2、未释放的内存、内存泄漏
char * str2 = malloc(sizeof(int));
free(str2);
// free(str2); //3、非法释放
return 0;
}
valgrind --tool=memcheck --leak-check=full --show-reachable=yes --trace-children=yes --log-file=out ./test
log
这个文件.在log文件最后会有个summary,其中对内存泄露进行了分类,总共有五类:
(1) “definitely lost” 意味着你的程序一定存在内存泄露;
(2)”indirectly lost”意味着你的程序一定存在内存泄露,并且泄露情况和指针结构相关.
(3) “possibly lost” 意味着你的程序一定存在内存泄露,除非你是故意进行着不符合常规的操作,例如将指针指向某个已分配内存块的中间位置。
(4) “still reachable” 意味着你的程序可能是没问题的,但确实没有释放掉一些本可以释放的内存。这种情况是很常见的,并且通常基于合理的理由。
(5)”suppressed” 意味着有些泄露信息被压制了。在默认的 suppression 文件中可以看到一些 suppression 相关设置。版权声明:本文为CSDN博主「深夜虫鸣」的原创文章,遵循 CC 4.0 BY-SA 版权协议,
原文链接:
https://blog.csdn.net/u010122972/article/details/78214174
注意:需要编译源文件的时候加上 -g
==47085== Memcheck, a memory error detector
==47085== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==47085== Using Valgrind-3.15.0 and LibVEX; rerun with -h for copyright info
==47085== Command: ./test
==47085==
==47085== Conditional jump or move depends on uninitialised value(s)
==47085== at 0x4E998DA: vfprintf (vfprintf.c:1642)
==47085== by 0x4EA1F25: printf (printf.c:33)
==47085== by 0x1086FE: main (test1.c:8)
==47085==
==47085== Use of uninitialised value of size 8 //8个字节的未初始化
==47085== at 0x4E9586B: _itoa_word (_itoa.c:179)
==47085== by 0x4E98F0D: vfprintf (vfprintf.c:1642)
==47085== by 0x4EA1F25: printf (printf.c:33)
==47085== by 0x1086FE: main (test1.c:8) //源码具体位置
==47085==
==47085== Conditional jump or move depends on uninitialised value(s)
==47085== at 0x4E95875: _itoa_word (_itoa.c:179)
==47085== by 0x4E98F0D: vfprintf (vfprintf.c:1642)
==47085== by 0x4EA1F25: printf (printf.c:33)
==47085== by 0x1086FE: main (test1.c:8)
==47085==
==47085== Conditional jump or move depends on uninitialised value(s)
==47085== at 0x4E99014: vfprintf (vfprintf.c:1642)
==47085== by 0x4EA1F25: printf (printf.c:33)
==47085== by 0x1086FE: main (test1.c:8)
==47085==
==47085== Conditional jump or move depends on uninitialised value(s)
==47085== at 0x4E99B4C: vfprintf (vfprintf.c:1642)
==47085== by 0x4EA1F25: printf (printf.c:33)
==47085== by 0x1086FE: main (test1.c:8)
==47085==
x [0]
==47085==
==47085== HEAP SUMMARY:
==47085== in use at exit: 10 bytes in 1 blocks
==47085== total heap usage: 3 allocs, 2 frees, 1,038 bytes allocated
==47085==
==47085== 10 bytes in 1 blocks are definitely lost in loss record 1 of 1 //没有释放malloc的内存
==47085== at 0x4C2FDFB: malloc (vg_replace_malloc.c:309)
==47085== by 0x108708: main (test1.c:10)
==47085==
==47085== LEAK SUMMARY:
==47085== definitely lost: 10 bytes in 1 blocks
==47085== indirectly lost: 0 bytes in 0 blocks
==47085== possibly lost: 0 bytes in 0 blocks
==47085== still reachable: 0 bytes in 0 blocks
==47085== suppressed: 0 bytes in 0 blocks
==47085==
==47085== Use --track-origins=yes to see where uninitialised values come from
==47085== For lists of detected and suppressed errors, rerun with: -s
==47085== ERROR SUMMARY: 6 errors from 6 contexts (suppressed: 0 from 0)
反着看,先看最底下的,再看上面的.
==25832== Invalid read of size 4
==25832== at 0x8048724: BandMatrix::ReSize(int, int, int) (bogon.cpp:45)
==25832== by 0x80487AF: main (bogon.cpp:66)
==25832== Address 0xBFFFF74C is not stack'd, malloc'd or free'd
25832 是进程ID
该程序对地址0xBFFFF74C进行了非法的4字节读取, 该地址不是有效的堆栈地址,也不对应于任何当前堆块或最近释放的堆块。读取发生在的第45行 bogon.cpp,从同一文件的第66行调用
检测重复错误的过程是非常昂贵的过程,并且如果您的程序生成大量错误,则可能会成为相当大的性能开销。
–error-limit=no
在Valgrind下运行的程序不会直接由CPU执行。它在Valgrind提供的合成CPU上运行。这就是为什么调试器在Valgrind上运行时无法调试程序的原因。
在使用Memcheck工具时使用GDB调试程序
valgrind --vgdb=yes --vgdb-error=0 ./test
在另一个shell中,启动GDB:
gdb ./test
//这个命令在valgrind那个线程里面有, 按照提示复制那个
(gdb) target remote | vgdb
退出gdb那个终端, valgrind就回退出
valgrind [valgrind-options] 原来的运行命令
最重要的选项是 --tool 决定要运行哪个Valgrind工具。
--tool= [default: memcheck]
toolname, 例如memcheck,cachegrind,callgrind,helgrind
--leak-check= [default: summary]
启用后,在客户端程序完成时搜索内存泄漏。如果设置为summary,则表示发生了多少泄漏。如果设置为full或 yes,则每个泄漏都将详细显示和/或计为错误,如选项--show-leak-kinds和 所指定 --errors-for-leak-kinds。
--show-reachable= , --show-possibly-lost=
这些选项提供了另一种方法来指定要显示的泄漏类型:
--show-reachable=no --show-possibly-lost=yes等同于 --show-leak-kinds=definite,possible。
--show-reachable=no --show-possibly-lost=no等同于 --show-leak-kinds=definite。
--show-reachable=yes等同于 --show-leak-kinds=all。
--show-leak-kinds= [default: definite,possible]
full 通过以下方式之一指定要在泄漏搜索中显示的泄漏种类:
用逗号分隔的一个或多个列表 definite indirect possible reachable。
all指定全套(所有泄漏种类)。等同于 --show-leak-kinds=definite,indirect,possible,reachable。
none 为空集。
--undef-value-errors= [default: yes]
控制Memcheck报告是否使用未定义的值错误。如果您不想看到未定义的值错误,请将此设置为no。它还具有一定程度加速Memcheck的副作用。
--track-origins= [default: no]
控制Memcheck是否跟踪未初始化值的来源。默认情况下,它不是,这意味着尽管它可以告诉您未初始化的值正在以危险的方式使用,但是它无法告诉您未初始化的值是从哪里来的。这通常使得很难找到根本问题。
definitely lost(绝对丢失)、indirectly lost(间接丢失)、 possibly lost(可能丢失)、 still reachable(仍可访问)、 suppressed(抑制)
如果–leak-check=full指定,则Memcheck将提供每个绝对丢失或可能丢失的块的详细信息,包括分配位置。
要显示的泄漏种类的默认值是 --show-leak-kinds=definite,possible。
==46004== Memcheck, a memory error detector
==46004== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==46004== Using Valgrind-3.15.0 and LibVEX; rerun with -h for copyright info
==46004== Command: ./test
==46004==
==46004==
==46004== HEAP SUMMARY:
==46004== in use at exit: 10 bytes in 1 blocks
==46004== total heap usage: 1 allocs, 0 frees, 10 bytes allocated
==46004==
@1==46004== 10 bytes in 1 blocks are definitely lost in loss record 1 of 1
==46004== at 0x4C2FDFB: malloc (vg_replace_malloc.c:309)
@1==46004== by 0x108662: main (test1.c:9)
==46004==
==46004== LEAK SUMMARY:
==46004== definitely lost: 10 bytes in 1 blocks
==46004== indirectly lost: 0 bytes in 0 blocks
==46004== possibly lost: 0 bytes in 0 blocks
==46004== still reachable: 0 bytes in 0 blocks
==46004== suppressed: 0 bytes in 0 blocks
==46004==
==46004== For lists of detected and suppressed errors, rerun with: -s
==46004== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
--leak-check=full
这个选项主要是会显示出来两个@1
的内容…
--show-leak-kinds=definite,possible
这个选项就是详细信息只会显示definite、possible的内存泄漏类型的详细信息.
valgrind --tool=memcheck --leak-check=full ./test
如果–leak-check=full指定,则Memcheck将提供每个绝对丢失或可能丢失的块的详细信息,包括分配位置。
#include
#include
int main(int argc, char *argv[]){
char * str1 = malloc(10); //2、未释放的内存、内存泄漏
return 0;
}
加上这个主要就是多了这些错误信息, 可以显示行号等信息.
==54477== 10 bytes in 1 blocks are definitely lost in loss record 1 of 1
==54477== at 0x4C2FDFB: malloc (vg_replace_malloc.c:309)
==54477== by 0x108662: main (test1.c:9)
valgrind --tool=memcheck --track-origins=yes ./test
–tool=memcheck 可以省略,默认选项
–track-origins=yes 更加详细的显示错误
#include
int main(int argc, char *argv[]){
// int x = 1;
int x;
printf("x [%d]\n\n", x); //使用未初始化的变量
return 0;
}
1、编译您的程序-g以包含调试信息,以便Memcheck的错误消息包含确切的行号。
适用于所有工具
-h --help
对核心和所选工具的所有选项显示帮助。
--version
显示Valgrind内核的版本号。
-v, --verbose
更加冗长。提供有关程序各个方面的额外信息,
--trace-children-skip=patt1,patt2,...
仅当--trace-children=yes指定时,此选项才有效。它允许一些孩子被跳过。
--trace-children= [default: no]
启用后,Valgrind将跟踪通过exec系统调用启动的子进程。这对于多进程程序是必需的。
请注意,Valgrind确实会跟踪到fork的子进程(由于fork创建了相同的进程副本,因此很难做到这一点,因此此选项的名称可谓是错误的。然而,大多数fork的子进程都会立即调用exec。
--vgdb= [default: yes]
当--vgdb=yes或--vgdb=full被指定时,Valgrind将提供“gdbserver”功能; 这使外部GNU GDB调试器在Valgrind上运行时可以控制和调试程序。 --vgdb=full会产生巨大的性能开销,但会提供更精确的断点和观察点。
11、与错误相关的选项
--xml= [default: no]
启用后,输出的重要部分(例如,工具错误消息)将采用XML格式,而不是纯文本。还必须使用的一个 --xml-fd,--xml-file或 --xml-socket到指定的XML将被发送。
--xml-fd= [default: -1, disabled]
指定Valgrind应该将其XML输出发送到指定的文件描述符。它必须与结合使用 --xml=yes。
--xml-file=
指定Valgrind应该将其XML输出发送到指定文件。
--xml-socket=
指定Valgrind应该在指定的IP地址将其XML输出发送到指定的端口。