valgrind内存查看工具介绍
- 格式:doc
- 大小:435.50 KB
- 文档页数:22
内存调试工具valgrind来源::linux下面用c++写代码,在所难免会遇到segmentation fault(段错误)。
个人在编写ns扩展模块时候,遇到过很多段错误,虽然运行时刻经常由程序抛出段错误,但是段错误的发生的程序级别的原因多种多样,不过归结到系统级别上,段错误都是由于内存原因引起的(个人总结)。
会造成内存错误的程序级别的原因,也就是我们程序员所经常犯的错误大致可以分为以下几个方面:1,使用未初始化的指针-这是必然的,指针指空的东西,必然出错。
2,重复删除一个指针-必然,再次删除就会删除一个已经分配给别的程序的数据或者其他。
3,内存冲突-由于程序声明的两块数据区域重叠,造成混乱。
4,混杂的指针错误-只能具体问题具体分析,情况比较复杂。
对于一位刚开始用c++在linux编程的人来说,最常遇到的应该的就是1与2了。
当工程规模比较大,程序由小组完成而后整合等的情况下,很容易出现2,3,4的情况。
这时候的调试比较麻烦,也需要很多耐心。
我在做的wimax mesh的项目就是这样。
对于一个timer的使用,没有初始化,造成的段错误,一目了然。
工程进展非常顺利。
当工程做到50%时候(11.08号),遇到了一个段错误,结果调试到12.02号才调出来!我就来说一下我的调试历程吧!真是一波三折阿!开始的时候以为是1或者2的情况,反复检查,不是这样。
然后怀疑3或者4,结果由于没有使用任何工具,只是在代码中加打印信息,这时候只能把错误定位到transmit(p)这个函数上。
但是这个函数我只写了一行,就是transmit(p){downtarget_-recv(p,(Handle*)NULL);}程序在这个地方出错实在让人摸不到头绪,因为再往下执行就不是我代码的问题了,而是下层已有代码甚至是系统代码的问题阿!非常困扰!然后开始用gdb调试,gdb是一个很好的很强大的调试工具,我用的命令行的,所能完成的功能和vc下的调试工具差不多,只是需要看什么变量就是要用print×来看罢了,不过功能决不比它差。
Linux 内存调试工具- Valgrind 使用初探Valgrind 是在linux系统下开发应用程序时用于调试内存问题的工具。
它尤其擅长发现内存管理的问题,它可以检查程序运行时的内存泄漏问题。
它的官方网址是/ 下载最新版本的Valgrind,目前是3.2.0。
wget/downloads/valValgrind 是在linux系统下开发应用程序时用于调试内存问题的工具。
它尤其擅长发现内存管理的问题,它可以检查程序运行时的内存泄漏问题。
它的官方网址是/下载最新版本的Valgrind,目前是3.2.0。
wget/downloads/valkyrie-1.2.0.tar.bz2执行常规的安装步骤:./confgure && make && make install。
注意:系统必须安装QT的开发包。
即便这样在make 时还是出现qplatformdefs.h这个文件找不到的情况,导致make失败。
查找系统中的qplatformdefs.h 之后,发现没有存在于qt的标准头文件目录/usr/lib/qt-3.3/include。
如是将/usr/lib/qt-3.3/mkspecs /linux-g++/ 目录下该头文件复制标准头文件目录,重新make ,后面一切OK。
初次使用编译如下代码: gcc -Wall example.c -g -o example#include <stdlib.h>void f(void){int* x = malloc(10 * sizeof(int));x[10] = 0; // problem 1: heap block overrun} // problem 2: memory leak -- x not freedint main(void){f();return 0;}注意:gcc 的-g 选项让Valgrind调试输出时指出相应信息的代码所在的行号。
Valgrind内存工具学习目录一. VALGRIND工具简介 (1)1.1V ALGRIND体系结构概述 (1)1.2L INUX内存空间布局 (2)二. VALGRIND的安装 (4)2.1在L INUX系统下的安装 (4)2.2在设备中的安装 (4)三. MEMCHECK模块使用 (4)3.1使用未初始化的内存 (5)3.2内存读写越界 (6)3.3内存覆盖 (7)3.4动态内存管理错误 (8)3.5内存泄露 (9)3.6内存管理规则 (12)四. MASSIF模块的使用 (13)4.1问题引出 (13)4.2运行MASSIF模块 (14)4.3运行MS_PRINT (14)4.4.OUT文件声明 (14)4.5内存分配趋势图说明 (15)4.6内存分配详细说明 (16)4.6.1 内存分配快照表 (16)4.6.2 分配函数内存详细 (17)4.7参数说明 (17)五. CACHEGRIND使用 (18)5.1使用命令: (18)5.2结果分析 (18)六. HELGRIND模块使用 (20)七. 附录 (20)一. Valgrind工具简介用于定位应用程序开发中的内存问题。
Valgrind是linux下开源的内存问题检测工具。
1.1 Valgrind体系结构概述Valgrind是一套Linux下,开放源代码(GPL V2)的仿真调试工具的集合。
Valgrind由内核(core)以及基于内核的其他调试工具组成。
内核类似于一个框架(framework),它模拟了一个CPU环境,并提供服务给其他工具;而其他工具则类似于插件(plug-in),利用内核提供的服务完成各种特定的内存调试任务。
Valgrind的体系结构如下图所示:图 1.1 Valgrind 体系结构Valgrind包括如下一些工具:Memcheck。
这是valgrind应用最广泛的工具,一个重量级的内存检查器,能够发现开发中绝大多数内存错误使用情况,比如:使用未初始化的内存,使用已经释放了的内存,内存访问越界等。
valgrind的使用Valgrind是一个GPL的软件,用于Linux(For x86, amd64 and ppc32)程序的内存调试和代码剖析。
你可以在它的环境中运行你的程序来监视内存的使用情况,比如C 语言中的malloc和free或者 C++中的new和 delete。
使用Valgrind的工具包,你可以自动的检测许多内存管理和线程的bug,避免花费太多的时间在bug寻找上,使得你的程序更加稳固。
Valgrind的主要功能Valgrind工具包包含多个工具,如Memcheck,Cachegrind,Helgrind, Callgrind,Massif。
下面分别介绍个工具的作用:Memcheck 工具主要检查下面的程序错误:∙使用未初始化的内存 (Use of uninitialised memory)∙使用已经释放了的内存(Reading/writing memory after it has been free’d) ∙使用超过 malloc分配的内存空间(Reading/writing off the end of malloc’d blocks)∙对堆栈的非法访问 (Reading/writing inappropriate areas on the stack) ∙申请的空间是否有释放 (Memory leaks –where pointers to malloc’d blocks are lost forever)∙malloc/free/new/delete申请和释放内存的匹配(Mismatched use of malloc/new/new [] vs free/delete/delete [])∙src和dst的重叠(Overlapping src and dst pointers in memcpy() and related functions)CallgrindCallgrind收集程序运行时的一些数据,函数调用关系等信息,还可以有选择地进行cache 模拟。
valgrind 原理
Valgrind是一个用于内存调试、内存泄漏检测和性能分析的开源工具。
其原理是基于动态二进制代码分析技朮。
Valgrind通过创建一个虚拟处理器环境来执行被分析的程序,然后在这个虚拟环境中对程序的指令进行解释执行,同时收集程序执行时的各种信息。
Valgrind的核心组件是Memcheck,它是用于检测内存错误的工具。
Memcheck通过在虚拟环境中跟踪每个分配的内存块,并记录其状态(已分配、已释放等),来检测内存泄漏、越界访问、未初始化内存访问等问题。
另外,Memcheck还能够检测并纠正一些常见的内存错误,比如使用未初始化的变量或释放已经释放的内存。
除了Memcheck之外,Valgrind还包括其他工具,如Cachegrind用于缓存分析、Callgrind用于程序性能分析、Helgrind用于多线程程序的并发错误检测等。
这些工具都利用Valgrind的动态二进制代码分析技朮,在虚拟环境中对程序进行执行和分析,从而实现各种不同类型的调试和性能分析功能。
总的来说,Valgrind的原理是通过创建虚拟环境,对程序进行动态二进制代码分析,从而实现对内存错误、性能问题等的检测和
分析。
它的独特之处在于能够在不修改程序源代码的情况下进行全面的调试和性能分析,极大地方便了开发人员进行程序调试和优化工作。
介绍一种常用的内存泄漏检测工具内存泄漏是软件开发中常见的问题之一,会导致程序运行变慢、崩溃或不可预料的行为。
为了及时发现和解决内存泄漏问题,开发人员通常会使用各种内存泄漏检测工具。
本文将介绍一种常用的内存泄漏检测工具——Valgrind。
Valgrind是一款强大的内存调试和性能分析工具,适用于Linux和其他类UNIX系统。
它支持多种编程语言,例如C、C++、Java等,而且提供了丰富的功能来帮助开发人员检测和调试内存泄漏问题。
Valgrind提供了Memcheck工具,是它最重要的组成部分之一。
Memcheck可以检测程序中的内存错误,包括内存泄漏、访问已释放内存、使用未初始化的内存等。
它通过在程序的每一个内存分配和释放操作上插入代码来监控内存的使用情况,并在发现错误时提供详细的报告。
这使得开发人员能够快速定位和修复内存泄漏问题。
Valgrind还提供了Cachegrind工具,可用于程序性能分析。
Cachegrind通过模拟CPU高速缓存的访问,帮助开发人员发现程序中的缓存未命中情况,以及其他与缓存相关的性能问题。
它可以提供关于指令执行次数、缓存命中率等统计信息,帮助开发人员进行性能的优化和调整。
除了Memcheck和Cachegrind,Valgrind还提供了其他一些有用的工具,例如Helgrind和DRD。
Helgrind主要用于检测并发程序中的竞争条件和死锁,能够在程序执行过程中动态地检测并发访问共享资源的错误。
DRD是一种用于检测C/C++多线程程序中的竞争条件的工具,可以帮助开发人员发现潜在的并发错误。
Valgrind还支持插件的扩展机制,允许开发人员创建自定义的工具。
这为开发人员提供了最大的灵活性,可以根据自己的需求设计和实现特定的内存检测工具。
使用Valgrind的步骤相对简单。
安装Valgrind并确保系统满足运行要求。
接下来,编译需要检测的程序,并使用Valgrind运行它。
valgrind查内存泄漏的原理Valgrind查内存漏漏的原理Valgrind是一款强大的开源工具,用于检测和调试C/C++程序中的内存错误,其中包括内存泄漏。
本文将从浅入深地解释Valgrind查找内存泄漏的原理。
什么是内存泄漏?内存泄漏是指在程序中动态分配的内存空间没有被正确释放的情况。
这种情况下,程序在运行时会持续地分配新的内存,而不释放旧的内存,最终导致内存耗尽,程序崩溃。
Valgrind的基本原理Valgrind通过内存虚拟化技术来检测和调试程序。
它创建了一个虚拟的执行环境,用于运行目标程序,并捕获程序对内存的读写操作。
Valgrind将目标程序对内存的读写操作转化为自己定义的指令序列,并在内存操作之前和之后插入检测代码。
这些检测代码会记录每次内存操作的详细信息,例如内存的分配和释放,读写操作的位置等。
通过分析这些检测代码,Valgrind能够检测出内存泄漏、非法内存访问、内存重复释放等问题。
Valgrind的工具集Valgrind包含了多个工具,其中最常用的工具是Memcheck。
Memcheck工具Memcheck是Valgrind工具集中最常用的工具,也是用于检测内存泄漏的工具。
它通过跟踪程序中动态分配的内存,并检测是否有未被释放的内存块,来发现内存泄漏的问题。
Memcheck使用了很多高级的技术来提高检测的准确性和效率,例如影子内存和引用计数。
影子内存影子内存是Valgrind中一个重要的概念。
Valgrind为每个字节的内存分配了一个额外的字节,用于存储元数据,比如内存是否已分配、是否已初始化等。
这个额外的字节就是影子内存。
当程序对内存进行读写时,Valgrind会检查对应的影子内存,以确定内存是否被正确使用。
如果发现不合法的操作,Valgrind会报告错误。
引用计数为了提高内存检测的效率,Valgrind使用了引用计数技术。
每个内存块都会记录它被引用的次数。
当程序对内存块进行分配或释放操作时,Valgrind会相应地更新引用计数。
valgrind memcheck用法Valgrind是一个开源的内存调试工具,可以帮助你检测程序中的内存错误。
Memcheck是Valgrind的一个重要组件,专门用于检测程序中的内存错误,包括使用未初始化的内存、使用已经释放的内存、越过内存边界等。
以下是使用Valgrind Memcheck的一般步骤:1.安装Valgrind:首先,你需要在你的系统上安装Valgrind。
对于大多数Linux发行版,你可以通过包管理器来安装。
例如,在Ubuntu上,你可以使用以下命令来安装Valgrind:arduinosudo apt-get install valgrind2.编译程序:在使用Valgrind运行程序之前,你需要先编译程序,以便生成可执行文件。
确保在编译时开启调试信息,以便Valgrind能够获取更多的信息。
例如,使用gcc编译器时,你可以使用以下命令编译程序:gcc -g -o myprogram myprogram.c3.使用Valgrind运行程序:一旦你有了可执行文件,就可以使用Valgrind来运行程序了。
使用以下命令来运行程序:bashvalgrind --tool=memcheck myprogram这将启动Memcheck工具来检测程序中的内存错误。
如果你的程序需要接受命令行参数,你可以将它们作为Valgrind命令的参数,例如:bashvalgrind --tool=memcheck myprogram arg1 arg2 ...4.查看结果:Valgrind会输出一个详细的报告,显示程序中潜在的内存错误。
报告将列出各种类型的错误,包括使用未初始化的内存、使用已经释放的内存、越过内存边界等。
你可以根据报告中的信息来修复程序中的错误。
以上就是使用Valgrind Memcheck的一般步骤。
请注意,Memcheck可能会使程序的运行速度变慢,因此在进行性能敏感的程序时需要谨慎使用。
valgrind内存泄漏分析概述valgrind 是 Linux 业界主流且⾮常强⼤的内存泄漏检查⼯具。
在其官⽹介绍中,内存检查(memcheck)只是其其中⼀个功能。
由于只⽤过其内存泄漏的检查,就不拓展分享 valgrind 其他功能了。
valgrind 这个⼯具不能⽤于调试正在运⾏的程序,因为待分析的程序必须在它特定的环境中运⾏,它才能分析内存。
内存泄漏分类valgrind 将内存泄漏分为 4 类。
明确泄漏(definitely lost):内存还没释放,但已经没有指针指向内存,内存已经不可访问间接泄漏(indirectly lost):泄漏的内存指针保存在明确泄漏的内存中,随着明确泄漏的内存不可访问,导致间接泄漏的内存也不可访问可能泄漏(possibly lost):指针并不指向内存头地址,⽽是指向内存内部的位置仍可访达(still reachable):指针⼀直存在且指向内存头部,直⾄程序退出时内存还没释放。
明确泄漏官⽅⽤户⼿册描述如下:This means that no pointer to the block can be found. The block is classified as "lost",because the programmer could not possibly have freed it at program exit, since no pointer to it exists.This is likely a symptom of having lost the pointer at some earlier point in theprogram. Such cases should be fixed by the programmer.其实简单来说,就是内存没释放,但已经没有任何指针指向这⽚内存,内存地址已经丢失。
定义⽐较好理解,就不举例了。
Valgrind内存工具学习目录一. VALGRIND工具简介 (1)1.1V ALGRIND体系结构概述 (1)1.2L INUX内存空间布局 (2)二. VALGRIND的安装 (4)2.1在L INUX系统下的安装 (4)2.2在设备中的安装 (4)三. MEMCHECK模块使用 (4)3.1使用未初始化的内存 (5)3.2内存读写越界 (6)3.3内存覆盖 (7)3.4动态内存管理错误 (8)3.5内存泄露 (9)3.6内存管理规则 (12)四. MASSIF模块的使用 (13)4.1问题引出 (13)4.2运行MASSIF模块 (14)4.3运行MS_PRINT (14)4.4.OUT文件声明 (14)4.5内存分配趋势图说明 (15)4.6内存分配详细说明 (15)4.6.1 内存分配快照表 (15)4.6.2 分配函数内存详细 (16)4.7参数说明 (17)五. CACHEGRIND使用 (17)5.1使用命令: (17)5.2结果分析 (17)六. HELGRIND模块使用 (19)七. 附录 (20)一. Valgrind工具简介用于定位应用程序开发中的内存问题。
Valgrind是linux下开源的内存问题检测工具。
1.1 Valgrind体系结构概述Valgrind是一套Linux下,开放源代码(GPL V2)的仿真调试工具的集合。
Valgrind由内核(core)以及基于内核的其他调试工具组成。
内核类似于一个框架(framework),它模拟了一个CPU环境,并提供服务给其他工具;而其他工具则类似于插件(plug-in),利用内核提供的服务完成各种特定的内存调试任务。
Valgrind的体系结构如下图所示:图 1.1 Valgrind 体系结构Valgrind包括如下一些工具:Memcheck。
这是valgrind应用最广泛的工具,一个重量级的内存检查器,能够发现开发中绝大多数内存错误使用情况,比如:使用未初始化的内存,使用已经释放了的内存,内存访问越界等。
这也是本文将重点介绍的部分。
Callgrind。
它主要用来检查程序中函数调用过程中出现的问题。
Cachegrind。
它主要用来检查程序中缓存使用出现的问题。
Helgrind。
它主要用来检查多线程程序中出现的竞争问题。
Massif。
它主要用来检查程序中堆栈使用中出现的问题。
Extension。
可以利用core提供的功能,自己编写特定的内存调试工具。
1.2 Linux内存空间布局Linux 程序内存空间布局要发现Linux下的内存问题,首先一定要知道在Linux下,内存是如何被分配的?下图展示了一个典型的Linux C程序内存空间布局:图 1.2 典型内存空间布局一个典型的Linux C程序内存空间由如下几部分组成:代码段(.text):这里存放的是CPU要执行的指令。
代码段是可共享的,相同的代码在内存中只会有一个拷贝,同时这个段是只读的,防止程序由于错误而修改自身的指令。
初始化数据段(.data):这里存放的是程序中需要明确赋初始值的变量,例如位于所有函数之外的全局变量:int val=100。
需要强调的是,以上两段都是位于程序的可执行文件中,内核在调用exec函数启动该程序时从源程序文件中读入。
未初始化数据段(.bss):位于这一段中的数据,内核在执行该程序前,将其初始化为0或者null。
例如出现在任何函数之外的全局变量:int sum;堆(Heap):这个段用于在程序中进行动态内存申请,例如经常用到的malloc,new系列函数就是从这个段中申请内存。
栈(Stack): 函数中的局部变量以及在函数调用过程中产生的临时变量都保存在此段中。
内存检查原理Memcheck检测内存问题的原理如下图所示:图 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,如果该值尚未初始化,则会报告使用未初始化内存错误。
二. Valgrind的安装2.1 在Linux系统下的安装版本:valgrind-3.4.1.tar.bz2下载地址:安装方法:1. bzip2 -d valgrind-3.4.1.tar.bz2 解压为tar文件2. tar –xvf valgrind-3.4.1.tar3. cd valgrind-3.4.14. ./configure5. Make install6. Valgrind –help使用说明7. 使用vi工具编写一个.c文件,例如:vi a.c8. gcc -o badloop badloop.c 生成可执行文件9. 再用valgrind 工具对可执行文件进行内存问题检测10. 对于massif模块,valgrind执行完之后会生成类似massif.out.12464的文件可以使用ms_print massif.out.12464 > massif.out.12464.log生成整理后的结果。
注:目前已经在10.14.14.182这台linux服务器上安装了valgrind2.2 在设备中的安装1.将valgrind.tar包在/lib/下解压缩2.将vlagrind程序放在/opt/nsfocus/bin/下即可三. Memcheck模块使用在设备里安装好valgrind后,如下述方法使用:RANK=0 valgrind --tool=memcheck –leak-check=full ./class.85 1在Linux平台开发应用程序时,最常遇见的问题就是错误的使用内存,我们总结了常见了内存错误使用情况,并说明了如何用valgrind将其检测出来。
3.1 使用未初始化的内存问题分析:对于位于程序中不同段的变量,其初始值是不同的,全局变量和静态变量初始值为0,而局部变量和动态申请的变量,其初始值为随机值。
如果程序使用了为随机值的变量,那么程序的行为就变得不可预期。
下面的程序就是一种常见的,使用了未初始化的变量的情况。
数组a是局部变量,其初始值为随机值,而在初始化时并没有给其所有数组成员初始化,如此在接下来使用这个数组时就潜在有内存问题。
清单3结果分析:假设这个文件名为:badloop.c,生成的可执行程序为badloop。
用memcheck对其进行测试,输出如下。
清单4输出结果显示,在该程序第11行中,程序的跳转依赖于一个未初始化的变量。
准确的发现了上述程序中存在的问题。
3.2 内存读写越界问题分析:这种情况是指:访问了你不应该/没有权限访问的内存地址空间,比如访问数组时越界;对动态内存访问时超出了申请的内存大小范围。
下面的程序就是一个典型的数组越界问题。
pt是一个局部数组变量,其大小为4,p初始指向pt数组的起始地址,但在对p循环叠加后,p超出了pt数组的范围,如果此时再对p 进行写操作,那么后果将不可预期。
清单5结果分析:假设这个文件名为badacc.cpp,生成的可执行程序为badacc,用memcheck对其进行测试,输出如下。
清单6输出结果显示,在该程序的第15行,进行了非法的写操作;在第16行,进行了非法读操作。
准确地发现了上述问题。
3.3 内存覆盖问题分析:C 语言的强大和可怕之处在于其可以直接操作内存,C 标准库中提供了大量这样的函数,比如strcpy, strncpy, memcpy, strcat 等,这些函数有一个共同的特点就是需要设置源地址(src),和目标地址(dst),src 和dst 指向的地址不能发生重叠,否则结果将不可预期。
下面就是一个src 和dst 发生重叠的例子。
在15 与17 行中,src 和dst 所指向的地址相差20,但指定的拷贝长度却是21,这样就会把之前的拷贝值覆盖。
第24 行程序类似,src(x+20) 与dst(x) 所指向的地址相差20,但dst 的长度却为21,这样也会发生内存覆盖。
清单7结果分析:假设这个文件名为badlap.cpp,生成的可执行程序为badlap,用memcheck 对其进行测试,输出如下。
清单8输出结果显示上述程序中第15,17,24行,源地址和目标地址设置出现重叠。
准确的发现了上述问题。
3.4 动态内存管理错误问题分析:常见的内存分配方式分三种:静态存储,栈上分配,堆上分配。
全局变量属于静态存储,它们是在编译时就被分配了存储空间,函数内的局部变量属于栈上分配,而最灵活的内存使用方式当属堆上分配,也叫做内存动态分配了。
常用的内存动态分配函数包括:malloc, alloc, realloc, new等,动态释放函数包括free, delete。
一旦成功申请了动态内存,我们就需要自己对其进行内存管理,而这又是最容易犯错误的。
下面的一段程序,就包括了内存动态管理中常见的错误。
清单9常见的内存动态管理错误包括:1. 申请和释放不一致由于C++ 兼容C,而C 与C++ 的内存申请和释放函数是不同的,因此在C++ 程序中,就有两套动态内存管理函数。
一条不变的规则就是采用C 方式申请的内存就用C 方式释放;用C++ 方式申请的内存,用C++ 方式释放。
也就是用malloc/alloc/realloc 方式申请的内存,用free 释放;用new 方式申请的内存用delete 释放。
在上述程序中,用malloc 方式申请了内存却用delete 来释放,虽然这在很多情况下不会有问题,但这绝对是潜在的问题。
2. 申请和释放不匹配申请了多少内存,在使用完成后就要释放多少。
如果没有释放,或者少释放了就是内存泄露;多释放了也会产生问题。
上述程序中,指针p和pt指向的是同一块内存,却被先后释放两次。
3. 释放后仍然读写本质上说,系统会在堆上维护一个动态内存链表,如果被释放,就意味着该块内存可以继续被分配给其他部分,如果内存被释放后再访问,就可能覆盖其他部分的信息,这是一种严重的错误,上述程序第16行中就在释放后仍然写这块内存。