一、valgrind简介

Valgrind工具套件提供了许多调试和分析工具,可帮助您使程序更快,更正确。这些工具中最受欢迎的是Memcheck。它可以检测许多与C和C ++程序中常见的内存相关的错误,这些错误可能导致崩溃和不可预测的行为。

标准配置提供了许多有用的工具:

  1. Memcheck是一个内存错误检测器。可以帮助你使程序更加正确。——这是valgrind应用最广泛的工具,一个重量级的内存检查器,能够发现开发中绝大多数内存错误使用情况,比如:使用未初始化的内存,使用已经释放了的内存,内存访问越界等。
  2. Cachegrind是一个缓存和分支预测分析器。可以帮助程序运行的更快。——它主要用来检查程序中缓存使用出现的问题。
  3. Callgrind是一个生成缓存分析器的调用图。和Cachegrind有一些重叠,也收集了Cachegrind没有的一些信息。——它主要用来检查程序中函数调用过程中出现的问题。
  4. Helgrind是一个线程错误检测器。可以帮助多线程程序更准确。——它主要用来检查多线程程序中出现的竞争问题。
  5. DRD也是线程错误检测器。他与Helgrind类似,但是用不同的分析技术,因此可能会发现不同的问题。
  6. Massif时一个堆分析器。可以帮助使程序使用更少的内存。——它主要用来检查程序中堆栈使用中出现的问题。
  7. DHAT时一种不同类型的对分析器。可以帮助了解块寿命,块利用率和效率低下的问题。
  8. SGcheck时一种实验工具,可以检测堆栈和全局数组的溢出。它的功能与Memcheck的功能互补:SGcheck发现Memcheck无法解决的问题,反之亦然。
  9. 小工具: Lackey是一个示例工具,用于说明一些仪器基础知识和
  10. 小工具:Nulgrind是最小的Valgrind工具,不进行分析或检测,仅用于测试目的。是最简单的Valgrind工具。它不执行任何程序或程序分析,只需正常运行即可。它主要用于Valgrind的开发人员进行调试和回归测试。尽管如此,您可以使用Nulgrind运行程序。它们的运行速度比正常情况慢5倍左右,没有任何有用的效果。Note that you need to use the option --tool=none to run Nulgrind (ie. not --tool=nulgrind).
  11. extension ------> 可以利用core提供的功能,自己编写特定的内存调试工具(不在我学习的范围中)

二、Ubuntu16.04下安装valgrind

Valgrind 安装,去官网下载: http://valgrind.org/downloads/current.html#current

我当前下载的版本为valgrind-3.15.0.tar.bz2

# tar -jxf valgrind-3.15.0.tar.bz2   ——解压

# cd /home/ranxf/valgrind-3.15.0

# vim README ——查看文档来确认安装过程

 0. Clone the code from GIT:
git clone git://sourceware.org/git/valgrind.git
There are further instructions at
http://www.valgrind.org/downloads/repository.html.  1. cd into the source directory. 2. Run ./autogen.sh to setup the environment (you need the standard
autoconf tools to do so). 3. Continue with the following instructions...   To install from a tar.bz2 distribution: 4. Run ./configure, with some options if you wish. The only interesting
one is the usual --prefix=/where/you/want/it/installed. 5. Run "make". 6. Run "make install", possibly as root if the destination permissions
require that. 7. See if it works. Try "valgrind ls -l". Either this works, or it
bombs out with some complaint. In that case, please let us know
(see http://valgrind.org/support/bug_reports.html). # ./configure --prefix=/workdisk/valgrind/ # 配置安装路径
# make # 从makefile中读取指令,然后编译
# make instal # 从makefile中读取指令,安装到指定位置 # vim /etc/profile
export PATH="$PATH:/workdisk/valgrind/bin"(环境变量配置)

三、验证valgrind是否安装成功

cd /workdisk/valgrind/bin

# ./valgrind ls -l
==31242== Memcheck, a memory error detector
==31242== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==31242== Using Valgrind-3.15.0 and LibVEX; rerun with -h for copyright info
==31242== Command: ls -l
==31242==
总用量 836
-rwxr-xr-x 1 root root 44737 8月 27 10:41 callgrind_annotate
-rwxr-xr-x 1 root root 12673 8月 27 10:41 callgrind_control
-rwxr-xr-x 1 root root 33535 8月 27 10:41 cg_annotate
-rwxr-xr-x 1 root root 10418 8月 27 10:41 cg_diff
-rwxr-xr-x 1 root root 315872 8月 27 10:41 cg_merge
-rwxr-xr-x 1 root root 24398 8月 27 10:41 ms_print
-rwxr-xr-x 1 root root 76816 8月 27 10:41 valgrind
-rwxr-xr-x 1 root root 104136 8月 27 10:41 valgrind-di-server
-rwxr-xr-x 1 root root 30176 8月 27 10:41 valgrind-listener
-rwxr-xr-x 1 root root 180680 8月 27 10:41 vgdb
==31242==
==31242== HEAP SUMMARY:
==31242== in use at exit: 19,848 bytes in 17 blocks
==31242== total heap usage: 228 allocs, 211 frees, 102,284 bytes allocated
==31242==
==31242== LEAK SUMMARY:
==31242== definitely lost: 0 bytes in 0 blocks
==31242== indirectly lost: 0 bytes in 0 blocks
==31242== possibly lost: 0 bytes in 0 blocks
==31242== still reachable: 19,848 bytes in 17 blocks
==31242== suppressed: 0 bytes in 0 blocks
==31242== Rerun with --leak-check=full to see details of leaked memory
==31242==
==31242== For lists of detected and suppressed errors, rerun with: -s
==31242== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
./valgrind --leak-check=full ls -l
==31322== Memcheck, a memory error detector
==31322== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==31322== Using Valgrind-3.15.0 and LibVEX; rerun with -h for copyright info
==31322== Command: ls -l
==31322==
总用量 836
-rwxr-xr-x 1 root root 44737 8月 27 10:41 callgrind_annotate
-rwxr-xr-x 1 root root 12673 8月 27 10:41 callgrind_control
-rwxr-xr-x 1 root root 33535 8月 27 10:41 cg_annotate
-rwxr-xr-x 1 root root 10418 8月 27 10:41 cg_diff
-rwxr-xr-x 1 root root 315872 8月 27 10:41 cg_merge
-rwxr-xr-x 1 root root 24398 8月 27 10:41 ms_print
-rwxr-xr-x 1 root root 76816 8月 27 10:41 valgrind
-rwxr-xr-x 1 root root 104136 8月 27 10:41 valgrind-di-server
-rwxr-xr-x 1 root root 30176 8月 27 10:41 valgrind-listener
-rwxr-xr-x 1 root root 180680 8月 27 10:41 vgdb
==31322==
==31322== HEAP SUMMARY:
==31322== in use at exit: 19,848 bytes in 17 blocks
==31322== total heap usage: 228 allocs, 211 frees, 102,284 bytes allocated
==31322==
==31322== LEAK SUMMARY:
==31322== definitely lost: 0 bytes in 0 blocks
==31322== indirectly lost: 0 bytes in 0 blocks
==31322== possibly lost: 0 bytes in 0 blocks
==31322== still reachable: 19,848 bytes in 17 blocks
==31322== suppressed: 0 bytes in 0 blocks
==31322== Reachable blocks (those to which a pointer was found) are not shown.
==31322== To see them, rerun with: --leak-check=full --show-leak-kinds=all
==31322==
==31322== For lists of detected and suppressed errors, rerun with: -s
==31322== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)

四、Valgrind 命令参数介绍

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

最常用的命令格式:

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

    -h –help 显示帮助信息。(除了以下参数,可用帮助-h查看更多信息)
--version 显示valgrind内核的版本,每个工具都有各自的版本。
-q –quiet 安静地运行,只打印错误信息。
-v –verbose 更详细的信息, 增加错误数统计。
--trace-children=no|yes 跟踪子线程? [no]
--track-fds=no|yes 跟踪打开的文件描述?[no]
--time-stamp=no|yes 增加时间戳到LOG信息? [no]
--log-fd=<number> 输出LOG到描述符文件 [2=stderr]
--log-file=<file> 将输出的信息写入到filename.PID的文件里,PID是运行程序的进行ID
--log-file-exactly=<file> 输出LOG信息到 file
--log-file-qualifier=<VAR> 取得环境变量的值来做为输出信息的文件名。 [none]
--log-socket=ipaddr:port 输出LOG到socket ,ipaddr:port

LOG信息输出

还是在-h中查看

   --xml=yes 将信息以xml格式输出,只有memcheck可用
--num-callers=<number> show <number> callers in stack traces [12]
--error-limit=no|yes 如果太多错误,则停止显示新错误? [yes]
--error-exitcode=<number> 如果发现错误则返回错误代码 [0=disable]
--db-attach=no|yes 当出现错误,valgrind会自动启动调试器gdb。[no]
--db-command=<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]

五、测试案例介绍

(一)测试demo

/workdisk# vim /workdisk/testcode/testValgrind.cc  # 在该路径下生成喊以下内容的testValgrind.cc文件(内存未释放)

#include <iostream>

using namespace std;

int main()
{
int *a = new int(); //delete a; return ;
}

(二)代码编译

root@ranxf-TEST:/workdisk/testcode# ls
testValgrind.cc
root@ranxf-TEST:/workdisk/testcode# g++ -g -o testValgrind testValgrind.cc
root@ranxf-TEST:/workdisk/testcode# ls
testValgrind testValgrind.cc

-o:指定生成可执行文件的名称。使用方法为:g++ -o afile file.cpp file.h ... (可执行文件不可与待编译或链接文件同名,否则会生成相应可执行文件且覆盖原编译或链接文件),如果不使用-o选项,则会生成默认可执行文件a.out。
-c:只编译不链接,只生成目标文件。
-g:添加gdb调试选项。

(三)代码单元测试

输入命令:orkdisk/testcode# /workdisk/valgrind/bin/valgrind --tool=memcheck --leak-check=full ./testValgrind
如果valgrind添加了环境变量,输入命令可以在任何路径下简化为:#valgrind --tool=memcheck --leak-check=full ./testValgrin
root@ranxf-TEST:/workdisk/testcode# /workdisk/valgrind/bin/valgrind --tool=memcheck --leak-check=full ./testValgrind
==== Memcheck, a memory error detector # 内存错误检测器
==== Copyright (C) -, and GNU GPL'd, by Julian Seward et al.
==== Using Valgrind-3.15. and LibVEX; rerun with -h for copyright info
==== Command: ./testValgrind
====
====
==== HEAP SUMMARY: # 堆摘要
==== in use at exit: , bytes in blocks # 退出时使用:2个数据块中有72708个字节
==== total heap usage: allocs, frees, , bytes allocated
====
==== bytes in blocks are definitely lost in loss record of 2 # 1个块中的4个字节在丢失记录1(共2个)中肯定丢失
==== at 0x4C2E4B6: operator new(unsigned long) (vg_replace_malloc.c:)
==== by 0x400717: main (testValgrind.cc:)
====
==== LEAK SUMMARY: 泄漏汇总
==== definitely lost: bytes in blocks 肯定泄露:1块中有4个字节
==== indirectly lost: bytes in blocks 间接泄露:0块0字节
==== possibly lost: bytes in blocks 可能泄露:0块0字节
==== still reachable: , bytes in blocks 仍然可以访问:1个块中有72704个字节
==== suppressed: bytes in blocks 抑制:0块0字节
==== Reachable blocks (those to which a pointer was found) are not shown. 不显示可访问块(找到指针的块)。
==== To see them, rerun with: --leak-check=full --show-leak-kinds=all 若要查看它们,请使用以下项重新运行:--leak check=full--show leak kinds=all
====
==== For lists of detected and suppressed errors, rerun with: -s 对于检测到的和抑制的错误列表,请使用-s重新运行。
==== ERROR SUMMARY: errors from contexts (suppressed: from ) 错误摘要:1个上下文中有1个错误(禁止:0到0)
root@ranxf-TEST:/workdisk/testcode#

Memcheck将内存泄露分为两种,一种是肯定的内存泄露(definitely lost),一种可能的内存泄露(possibly lost);

Definitely lost 是指已经不能够访问这块内存;

  Definitely lost又分为两种:直接的(direct)泄露和间接的(indirect)泄露

    直接泄露是没有任何指针指向该内存;

    间接泄露是指指向该内存的指针都位于内存泄露处;

Possibly lost 是指仍然存在某个指针能够访问某块内存,但该指针指向的已经不是该内存首地址。

(四)测试代码

代码1. 使用未初始化的内存(程序名为valgrindTestCode1.cpp )

#include <iostream>
using namespace std;
int main()
{
int a[];
int i,s=;
a[]=a[]=a[]=a[]=;
for(i=;i<;i++)
s=s+a[i];
if(s==)
cout<<"sum is 33"<<endl;
else
cout<<"sum is not 33"<<endl;
return ;
}

数组a中的第二个元素未进行初始化,但是在for循环中依然访问链数组a的第二个元素。这就是使用未初始化的元素问题。在使用g++编译器对该程序编译并运行,结果如下:

root@ranxf-TEST:/workdisk/testcode# g++ -g -o TectCode1 valgrindTestCode1.cpp
root@ranxf-TEST:/workdisk/testcode# ls
TectCode1 testValgrind testValgrind.cc valgrindTestCode1.cpp
root@ranxf-TEST:/workdisk/testcode# ./TectCode1
sum is not

程序在编译和运行过程中并没有报出任何错误,异常和警告。

但实际上,程序存在一个巨大的隐患,那就是对未初始化的内存进行访问。我们使用valgrind对该程序进行检测,结果如下所示:

root@ranxf-TEST:/workdisk/testcode# valgrind ./TectCode1  或者 valgrind --tool=memcheck --leak-check=full ./TectCode1  # valgrind默认为内存错误检测器
==== Memcheck, a memory error detector
==== Copyright (C) -, and GNU GPL'd, by Julian Seward et al.
==== Using Valgrind-3.15. and LibVEX; rerun with -h for copyright info
==== Command: ./TectCode1
====
==22985== Conditional jump or move depends on uninitialised value(s)
==22985== at 0x400910: main (valgrindTestCode1.cpp:10) (此处要求我们在进行g++编译时添加-g参数,不然便给不出具体行数的提示)
====
sum is not
====
==== HEAP SUMMARY:
==== in use at exit: , bytes in blocks
==== total heap usage: allocs, frees, , bytes allocated
====
==== LEAK SUMMARY:
==== definitely lost: bytes in blocks
==== indirectly lost: bytes in blocks
==== possibly lost: bytes in blocks
==== still reachable: , bytes in blocks
==== suppressed: bytes in blocks
==== Rerun with --leak-check=full to see details of leaked memory

从上图结果中可以清晰的看到,提示出1个错误,提示信息为:“Conditional jump or move depends on uninitialised value(s)”,并且提示了错误位置在源文件test1.cpp中的第10行(此处要求我们在进行g++编译时添加-g参数,不然便给不出具体行数的提示)

代码2:内存读写越界


 #include <stdlib.h>
#include <iostream>
using namespace std;
int main()
{
int len=;
int *pt=(int *)malloc(len*sizeof(int));
int *p=pt;
for(int i=;i<len;i++)
p++;
*p=;
cout<<"the value of p is"<<*p<<endl;
return ;
}

在程序2中,p指针首先指向了malloc出的4个字节的地址。
之后执行了四次自增运算。也就是p指针自增运算后与初始地址相比偏移了32个字节。
偏移后的地址空间在程序中并没有申请。所以,p指针变成链野指针。
程序中并且又对p的地址空间进行写操作。这就造成链内存读写越界的问题。
 ———————————————— 
在使用g++编译器对该程序编译并运行,结果如下:
root@ranxf-TEST:/workdisk/testcode# g++ -g -o TestCode2 valgrindTestCode2.cpp
root@ranxf-TEST:/workdisk/testcode# ./TestCode2
the value of p is5
/workdisk/testcode# valgrind ./TestCode2
==== Memcheck, a memory error detector
==== Copyright (C) -, and GNU GPL'd, by Julian Seward et al.
==== Using Valgrind-3.15. and LibVEX; rerun with -h for copyright info
==== Command: ./TestCode2
====
==26714== Invalid write of size 4
==26714== at 0x400921: main (valgrindTestCode2.cpp:11)
==== Address 0x5ab7c90 is bytes after a block of size alloc'd
==== at 0x4C2DE96: malloc (vg_replace_malloc.c:)
==== by 0x4008F6: main (valgrindTestCode2.cpp:)
====
==26714== Invalid read of size 4
==26714== at 0x40092B: main (valgrindTestCode2.cpp:12)
==== Address 0x5ab7c90 is bytes after a block of size alloc'd
==== at 0x4C2DE96: malloc (vg_replace_malloc.c:)
==== by 0x4008F6: main (valgrindTestCode2.cpp:)
====
the value of p is5
====
==== HEAP SUMMARY:
==== in use at exit: , bytes in blocks
==== total heap usage: 3 allocs, 1 frees, 73,744 bytes allocated
====
==== LEAK SUMMARY:
==== definitely lost: bytes in blocks
==== indirectly lost: bytes in blocks
==== possibly lost: bytes in blocks
==== still reachable: , bytes in blocks
==== suppressed: bytes in blocks
==== Rerun with --leak-check=full to see details of leaked memory
====
==== For lists of detected and suppressed errors, rerun with: -s
==== ERROR SUMMARY: errors from contexts (suppressed: from )

从上图结果中可以清晰的看到,提示出2个错误,提示信息分别为:“Invalid write of size 4”和“Invalid read of size 4”,并且提示了错误位置在源文件test2.cpp中的第11行和第12行。并且检测提示了:“total heap usage: 3 allocs, 1 frees, 73,744 bytes allocated”。有内存泄漏。

代码3. 内存覆盖

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
char x[];
int i;
for(i=;i<;i++)
x[i]=i+;
strncpy(x+,x,);
strncpy(x+,x,);
strncpy(x,x+,);
strncpy(x,x+,);
x[]='\0';
strcpy(x,x+);
x[]=;
x[]='\0';
strcpy(x,x+);
return ;
} 在代码3中,strncpy(x+,x,),strncpy(x,x+,),strcpy(x,x+)这三条语句,在进行字符串复制过程中,复制与被复制的字符串空间存在交集。
通过复制操作,会改变初始字符串空间中的值。这就是内存覆盖的问题。在使用g++编译器对该程序编译并运行,结果如下: root@ranxf-TEST:/workdisk/testcode# g++ -g -o TestCode3 valgrindTestCode3.cpp
root@ranxf-TEST:/workdisk/testcode# ./TestCode3
root@ranxf-TEST:/workdisk/testcode#
可以从上图中发现,程序在编译和运行过程中并没有报出任何错误,异常和警告。
但实际上存在内存覆盖的问题,当我们不注意,再去使用原始字符串时,已经不是原来那个字符串了。
我们使用valgrind对该程序进行检测,结果如下所示: root@ranxf-TEST:/workdisk/testcode# valgrind ./TestCode3
==== Memcheck, a memory error detector
==== Copyright (C) -, and GNU GPL'd, by Julian Seward et al.
==== Using Valgrind-3.15. and LibVEX; rerun with -h for copyright info
==== Command: ./TestCode3
====
==== Source and destination overlap in strncpy(0x1fff0003c9, 0x1fff0003b5, 21)
==== at 0x4C31706: __strncpy_sse2_unaligned (vg_replace_strmem.c:)
==== by 0x400648: main (valgrindTestCode3.cpp:11)
====
==== Source and destination overlap in strncpy(0x1fff0003b5, 0x1fff0003c9, 21)
==== at 0x4C31706: __strncpy_sse2_unaligned (vg_replace_strmem.c:)
==== by 0x400680: main (valgrindTestCode3.cpp:13)
====
==== Source and destination overlap in strcpy(0x1fff0003a0, 0x1fff0003b4)
==== at 0x4C311C6: strcpy (vg_replace_strmem.c:)
==== by 0x4006BA: main (valgrindTestCode3.cpp:18)
====
====
==== HEAP SUMMARY:
==== in use at exit: bytes in blocks
==== total heap usage: allocs, frees, bytes allocated
====
==== All heap blocks were freed -- no leaks are possible
====
==== For lists of detected and suppressed errors, rerun with: -s
==== ERROR SUMMARY: errors from contexts (suppressed: from ) 提示三个错误,红色标识部分,并提示源文件中的错误行号11行,13行和18行

代码4、动态内存管理错误

 #include <iostream>
#include <stdlib.h>
int main()
{
int i;
char *p=(char *)malloc();
char *pt=p;
for(i=;i<;i++)
{
p[i]='z';
}
delete p;
pt[]='x';
free(pt);
return ;
}
在程序4中,使用malloc申请空间,使用delete释放空间,两者不匹配。使用malloc申请了10个字节的空间,只释放了一个字节空间。另外,对释放的空间仍然进行了读写操作。这些是典型的内存管理错误问题。在使用g++编译器对该程序编译并运行,结果如下

root@ranxf-TEST:/workdisk/testcode# g++ -g -o TestCode4 valgrindTestCode4.cpp
root@ranxf-TEST:/workdisk/testcode# ./TestCode4
*** Error in `./TestCode4': double free or corruption (fasttop): 0x00000000023dfc20 ***
……
已放弃 (核心已转储) 程序在运行中报出内存错误,但没有给出具体信息。我们使用valgrind对该程序进行检测,结果如下所示 root@ranxf-TEST:/workdisk/testcode# valgrind ./TestCode4
==== Memcheck, a memory error detector
==== Copyright (C) -, and GNU GPL'd, by Julian Seward et al.
==== Using Valgrind-3.15. and LibVEX; rerun with -h for copyright info
==== Command: ./TestCode4
====
==== Mismatched free() / delete / delete []
==== at 0x4C2F440: operator delete(void*) (vg_replace_malloc.c:)
==== by 0x4007E2: main (valgrindTestCode4.cpp:)
==== Address 0x5ab7c80 is bytes inside a block of size alloc'd
==== at 0x4C2DE96: malloc (vg_replace_malloc.c:)
==== by 0x4007A7: main (valgrindTestCode4.cpp:)
====
==== Invalid write of size
==== at 0x4007EB: main (valgrindTestCode4.cpp:)
==== Address 0x5ab7c81 is bytes inside a block of size free'd
==== at 0x4C2F440: operator delete(void*) (vg_replace_malloc.c:)
==== by 0x4007E2: main (valgrindTestCode4.cpp:)
==== Block was alloc'd at
==== at 0x4C2DE96: malloc (vg_replace_malloc.c:)
==== by 0x4007A7: main (valgrindTestCode4.cpp:)
====
==== Invalid free() / delete / delete[] / realloc()
==== at 0x4C2EF90: free (vg_replace_malloc.c:)
==== by 0x4007F9: main (valgrindTestCode4.cpp:)
==== Address 0x5ab7c80 is bytes inside a block of size free'd
==== at 0x4C2F440: operator delete(void*) (vg_replace_malloc.c:)
==== by 0x4007E2: main (valgrindTestCode4.cpp:)
==== Block was alloc'd at
==== at 0x4C2DE96: malloc (vg_replace_malloc.c:)
==== by 0x4007A7: main (valgrindTestCode4.cpp:)
====
====
==== HEAP SUMMARY:
==== in use at exit: , bytes in blocks
==== total heap usage: allocs, frees, , bytes allocated
====
==== LEAK SUMMARY:
==== definitely lost: bytes in blocks
==== indirectly lost: bytes in blocks
==== possibly lost: bytes in blocks
==== still reachable: , bytes in blocks
==== suppressed: bytes in blocks
==== Rerun with --leak-check=full to see details of leaked memory
====
==== For lists of detected and suppressed errors, rerun with: -s
==== ERROR SUMMARY: errors from contexts (suppressed: from )
root@ranxf-TEST:/workdisk/testcode#
从上图结果中可以清晰的看到,提示出的3个错误。
  使用malloc申请空间,使用delete释放空间,两者不匹配问题:
    “Mismatched free() / delete / delete []”;
  使用malloc申请链10个字节的空间,只释放链一个字节空间:
    “ Invalid free() / delete / delete[] / realloc()”;
  对释放空间仍然进行读写操作:
    “Invalid write of size 1”;

代码5:内存泄露

以下代码中分别存在makefile  test.cpp  tree.cpp  tree.h四个文件中

 1 /* makefile文件

 test:test.o tree.o
g++ -g -o test test.o tree.o
tree.o:tree.cpp tree.h
g++ -g -c tree.cpp -o tree.o
test.o:test.cpp
g++ -g -c test.cpp -o test.o /* tree.h文件
#ifndef _TREE_
#define _TREE_
typedef struct _node{
struct _node *l;
struct _node *r;
char v;
}node;
node *mk(node *l,node *r,char val);
void nodefr(node *n);
#endif / * test.cpp文件
#include <iostream>
#include "tree.h"
int main()
{
node *tree1,*tree2,*tree3;
tree1=mk(mk(mk(0,0,'3'),0,'2'),0,'1');
tree2=mk(0,mk(0,mk(0,0,'6'),'5'),'4');
tree3=mk(mk(tree1,tree2,'8'),0,'7');
return 0;
}
35
/* tree.cpp文件 #include <stdlib.h>
#include "tree.h"
node *mk(node *l,node *r,char val)
{
node *f=(node *)malloc(sizeof(*f));
f->l=l;
f->r=r;
f->v=val;
return f;
}
void nodefr(node *n)
{
if(n){
nodefr(n->l);
nodefr(n->r);
free(n);
}
}

在程序5中,使用malloc申请空间后,没有使用free函数释放申请的内存地址造成内存泄漏。在使用g++编译器对该程序编译并运行,结果如下:

 root@ranxf-TEST:/workdisk/testcode/valgrindTestCode5# ls
makefile test.cpp tree.cpp tree.h
root@ranxf-TEST:/workdisk/testcode/valgrindTestCode5# make
g++ -g -c test.cpp -o test.o
g++ -g -c tree.cpp -o tree.o
g++ -g -o test test.o tree.o
root@ranxf-TEST:/workdisk/testcode/valgrindTestCode5# root@ranxf-TEST:/workdisk/testcode/valgrindTestCode5# ls
makefile  test  test.cpp  test.o  tree.cpp  tree.h  tree.o
root@ranxf-TEST:/workdisk/testcode/valgrindTestCode5# ./test

可以从上图中发现,程序在编译和运行过程中并没有报出任何错误,异常和警告。但实际上存在内存泄漏的问题。我们使用valgrind对该程序进行检测,结果如下所示:

 root@ranxf-TEST:/workdisk/testcode/valgrindTestCode5# valgrind ./test
==== Memcheck, a memory error detector
==== Copyright (C) -, and GNU GPL'd, by Julian Seward et al.
==== Using Valgrind-3.15. and LibVEX; rerun with -h for copyright info
==== Command: ./test
====
====
==== HEAP SUMMARY:
==== in use at exit: , bytes in blocks
10 ==6852== total heap usage: 9 allocs, 0 frees, 72,896 bytes allocated
====
==== LEAK SUMMARY:
13 ==6852== definitely lost: 24 bytes in 1 blocks # 提示直接内存泄露
14 ==6852== indirectly lost: 168 bytes in 7 blocks # 提示间接内存泄露
==== possibly lost: bytes in blocks
==== still reachable: , bytes in blocks
==== suppressed: bytes in blocks
==== Rerun with --leak-check=full to see details of leaked memory
====
==== For lists of detected and suppressed errors, rerun with: -s
==== ERROR SUMMARY: errors from contexts (suppressed: from )

由此看到:“total heap usage: 8 allocs, 0 frees, 96 bytes allocated”。

提示间接内存泄漏:“indirectly lost: 84 bytes in 7 blocks”;

提示直接内存泄漏:“definitely lost: 12 bytes in 1 blocks”

间接内存泄漏指:指向该内存的指针都位于内存泄漏处;

直接泄漏时指:没有任何指针指向该内存。

本篇中的代码样例及相关内容都来自于学习徐晓鑫女士编著的《后台开发核心技术与应用实践》所得,特此声明。

程序相关源码下载地址:https://github.com/XiaoYaoNet/Valgrind_Memset

参考文章:

  valgrind 工具介绍和简单的使用

  Valgrind工具之内存检测

  valgrind 用法详见:http://blog.csdn.net/sduliulun/article/details/7732906

valgrind 性能测试工具学习使用的更多相关文章

  1. 【学习笔记】Iperf3网络性能测试工具

    [学习笔记]Iperf3网络性能测试工具 网络性能评估主要是监测网络带宽的使用率,将网络带宽利用最大化是保证网络性能的基础,但是由于网络设计不合理.网络存在安全漏洞等原因,都会导致网络带宽利用率不高. ...

  2. 性能测试学习第二天_性能测试工具概述Loadrunner介绍

    性能测试工具概述Loadrunner介绍 http://www.51testing.com/html/42/n-6542.html 其中,T直接影响用户体验时间 性能测试的原理: 记录一个访问过程的通 ...

  3. 性能测试工具 转自https://yq.aliyun.com/articles/35149?spm=5176.100239.blogcont35147.8.rsow6k

    摘要: 继续这个系列的学习,这一节重点介绍目前流行的性能测试工具以及如何选择适合项目的工具.在此之前,我已经对性能测试工具的原理与架构做了分析. http://www.cnblogs.com/fnng ...

  4. 理解 OpenStack + Ceph (8): 基本的 Ceph 性能测试工具和方法

    本系列文章会深入研究 Ceph 以及 Ceph 和 OpenStack 的集成: (1)安装和部署 (2)Ceph RBD 接口和工具 (3)Ceph 物理和逻辑结构 (4)Ceph 的基础数据结构 ...

  5. 开源多线程性能测试工具-sysbench

    导读 sysbench是一款开源的多线程性能测试工具,可以执行CPU/内存/线程/IO/数据库等方面的性能测试.数据库目前支持MySQL/Oracle/PostgreSQL.本文主要演示Mysql测试 ...

  6. 【转】开源性能测试工具 - Apache ab 介绍

    版权声明:本文可以被转载,但是在未经本人许可前,不得用于任何商业用途或其他以盈利为目的的用途.本人保留对本文的一切权利.如需转载,请在转载是保留此版权声明,并保证本文的完整性.也请转贴者理解创作的辛劳 ...

  7. Web网站的性能测试工具

    随着Web 2.0技术的迅速发展,许多公司都开发了一些基于Web的网站服务,通常在设计开发Web应用系统的时候很难模拟出大量用户同时访问系统的实际情况,因此,当Web网站遇到访问高峰时,容易发生服务器 ...

  8. 性能测试工具 wrk 使用教程

    文章首发自个人微信公众号:小哈学Java 个人网站地址:https://www.exception.site/wrk 被面试官经常问到之前开发的系统接口 QPS 能达到多少,经常给不出一个数值,支支吾 ...

  9. 数据库之redis篇(2)—— redis配置文件,常用命令,性能测试工具

    redis配置 如果你是找网上的其他教程来完成以上操作的话,相信你见过有的启动命令是这样的: 启动命令带了这个参数:redis.windows.conf,由于我测试环境是windows平台,所以是这个 ...

随机推荐

  1. rocketMQ broker 分发并处理请求

    使用 netty 监听端口 // org.apache.rocketmq.remoting.netty.NettyRemotingServer#start ServerBootstrap childH ...

  2. 运行上次失败用例(--lf 和 --ff)

    前言 “80%的bug集中在20%的模块,越是容易出现bug的模块,bug是越改越多“平常我们做手工测试的时候,比如用100个用例需要执行,其中10个用例失败了,当开发修复完bug后,我们一般是重点测 ...

  3. NFA转换为等价的DFA

    在编译系统中,词法分析阶段是整个编译系统的基础.对于单词的识别,有限自动机FA是一种十分有效的工具.有限自动机由其映射f是否为单值而分为确定的有限自动机DFA和非确定的有限自动机NFA.在非确定的有限 ...

  4. adobe Keychain mac

    Keychain password access This question has been Answered. janec2070563 May 8, 2018 11:07 AM I consta ...

  5. Prometheus Querying Function rate() vs irate()

    rate() rate(v range-vector) calculates the per-second average rate of increase of the time series in ...

  6. 浅谈spring配置定时任务的几种方式

    网上看到好多关于定时任务的讲解,以前只简单使用过注解方式,今天项目中看到基于配置的方式实现定时任务,自己做个总结,作为备忘录吧. 基于注解方式的定时任务 首先spring-mvc.xml的配置文件中添 ...

  7. C# 字符串、字节数组互相转换

    /// <summary> /// MD5加密 /// </summary> /// <param name="sender"></par ...

  8. 为应用创建多个独立python运行环境

    在开发Python应用程序的时候,系统安装的Python3只有一个版本:3.4.所有第三方的包都会被pip安装到Python3的site-packages目录下. 如果我们要同时开发多个应用程序,那这 ...

  9. IIS web服务器与ASP.NET

    参考教程:MVC网站项目发布到IIS服务器 https://jingyan.baidu.com/article/92255446574e11851648f4e4.html https://blog.c ...

  10. springboot - 应用实践(2)第一个springboot应用

    1.使用maven创建一个快速启动项目 2.引入相关依赖 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:x ...