内存溢出(out of memory)和内存泄露(memory leak)的区别和检测工具方法

2023-11-07

内存溢出 out of memory,是指程序在申请内存时,没有足够的内存空间供其使用,出现out of memory;比如申请了一个integer,但给它存了long才能存下的数,那就是内存溢出。

内存泄露 memory leak,是指程序在申请内存后,无法释放已申请的内存空间,一次内存泄露危害可以忽略,但内存泄露堆积后果很严重,无论多少内存,迟早会被占光。

memory leak会最终会导致out of memory!

内存溢出就是你要求分配的内存超出了系统能给你的,系统不能满足需求,于是产生溢出。 

    内存泄漏是指你向系统申请分配内存进行使用(new),可是使用完了以后却不归还(delete),结果你申请到的那块内存你自己也不能再访问(也许你把它的地址给弄丢了),而系统也不能再次将它分配给需要的程序。一个盘子用尽各种方法只能装4个果子,你装了5个,结果掉倒地上不能吃了。这就是溢出!比方说栈,栈满时再做进栈必定产生空间溢出,叫上溢,栈空时再做退栈也产生空间溢出,称为下溢。就是分配的内存不足以放下数据项序列,称为内存溢出. 

 

 

1.2.内存泄露的检测

 

(1)利用内存泄露检测工具

常用的有 BoundsCheaker、Deleaker、Visual Leak Detector等,工具毕竟熟能生巧,用户选择先自己喜欢的一款去用即可。

BoundsChecker没有找到win7下支持VS2005的破解版,用盗版的伤不起啊。

(2)使用Deleaker(本文采用vs2005)进行内存泄露检查

如下图所示:

A) Deleak安装后自动集成到VS中,在VS“工具”菜单中会加入一个“Deleaker”菜单项。

B) Deleaker能够对GDI,USER对象以及句柄进行检测,是否及时释放。

C) Deleaker能够检测泄露的内存发生地点,即展示其函数栈;双击能够转到相应的文件;

PS:Deleaker对中文不支持

如果有内存泄露Deleaker会在程序调试完弹出对话框如下图所示:

(3)使用Viual Leak detector

使用Deleak方便灵活,除了其对中文路径支持问题,但感觉和vs的集成度并不是很高。

Viual Leak detector安装后,要在VS中设置相应的头文件和库路径,在Debug模式下如果要检测相应源文件的内存泄露,则加上"#include <vld.h>"即可;

这样在检测内存泄露,可以在VS的输出窗口进行输出,感觉和VS的集成度更高,结果如下图所示:

同样能够显示 内存泄露处的 调用栈,并且通过双击也可以跳转到文件的内存泄露行,个人还是比较喜欢这种方式的。

(4)在没有工具的情况下,使用crtdbg.h中的api也是个很棒的选择

在MFC中可以看到在程序退出的时候,输出框内结尾部分输出内存泄露,并且点击可以跳转到内存泄露的代码处。

那么在console程序下呢,当然我们同样可以做到(做那些MFC帮我们完成了的细节);

A) _CrtSetDbgFlag函数

 

[cpp] view plaincopy

  1. int _CrtSetDbgFlag(  
  2. int newFlag  
  3. );  

 

(函数详细信息参考:http://msdn.microsoft.com/zh-cn/library/5at7yxcs.aspx

这个函数用于控制debug模式下堆管理的分配行为;

在main函数开始处添加:

 

[cpp] view plaincopy

  1. _CrtSetDbgFlag(_CrtSetDbgFlag(_CRTDBG_REPORT_FLAG) | _CRTDBG_LEAK_CHECK_DF);  
  2. //_CRTDBG_REPORT_FLAG:表示获取当前的标示位  
  3. //_CRTDBG_LEAK_CHECK_DF:表示检测内存泄露  

 

则如果出现内存泄露Debug结束后,输出框将输出:

{150}表示申请的第150块申请的内存空间;

B) 显示内存泄露所在的文件以及行

能够知道有内存泄露是不够的,更需要的信息是哪里内存泄露了?

我们可以在每个源文件的开头定义写这样一条宏定义:

 

[cpp] view plaincopy

  1. //根据__FILE___和__LINE__能够确定文件和行  
  2. #define new   new(_NORMAL_BLOCK, __FILE__, __LINE__)    


C) 显示内存泄露处的堆栈

 

[cpp] view plaincopy

  1. //lBreakAlloc,在申请的堆区序号为lBreakAlloc处设置一个断点  
  2. long _CrtSetBreakAlloc( long lBreakAlloc );  

(函数详细信息参考:http://technet.microsoft.com/zh-cn/library/aa246759

 

此函数在指定的申请堆区空间次序处(即lBreakAlloc)设置断点;

很喜欢这个函数,这个函数结合"A)"中提到的{150},比如使用方法:

 

[cpp] view plaincopy

  1. _CrtSetBreakAlloc(150); //则在第150次申请堆空间时候设置断点  

 

这样就可以看到函数调用栈,从而帮助我们更加精确的定位程序泄露的位置(调用栈可是个好玩意)。

 

个人感觉这种方式虽然要手动的修改代码,但其功能却比前两个工具的有效,因为能够在程序运行的时候查看调用栈,这就意味着能够调试程序。

展示结果如下图所示(自动在第150次申请堆空间处中断):

1.3内存泄露检测工具比较   

1.     ccmalloc-Linux和Solaris下对C和C++程序的简单的使用内存泄漏和malloc调试库。

2.     Dmalloc-Debug Malloc Library.

3.     Electric Fence-Linux分发版中由Bruce Perens编写的malloc()调试库。

4.     Leaky-Linux下检测内存泄漏的程序。

5.     LeakTracer-Linux、Solaris和HP-UX下跟踪和分析C++程序中的内存泄漏。

6.     MEMWATCH-由Johan Lindh编写,是一个开放源代码C语言内存错误检测工具,主要是通过gcc的precessor来进行。

7.     Valgrind-Debugging and profiling Linux programs, aiming at programs written in C and C++.

8.     KCachegrind-A visualization tool for the profiling data generated by Cachegrindand Calltree.

9.     Leak Monitor-一个Firefox扩展,能找出跟Firefox相关的泄漏类型。

10. IE Leak Detector (Drip/IE Sieve)-Drip和IE Sieve leak detectors帮助网页开发员提升动态网页性能通过报告可避免的因为IE局限的内存泄漏。

11. Windows Leaks Detector-探测任何Win32应用程序中的任何资源泄漏(内存,句柄等),基于Win API调用钩子。

12. SAP Memory Analyzer-是一款开源的JAVA内存分析软件,可用于辅助查找JAVA程序的内存泄漏,能容易找到大块内存并验证谁在一直占用它,它是基于Eclipse RCP(Rich Client Platform),可以下载RCP的独立版本或者Eclipse的插件。

13. DTrace-即动态跟踪Dynamic Tracing,是一款开源软件,能在Unix类似平台运行,用户能够动态检测操作系统内核和用户进程,以更精确地掌握系统的资源使用状况,提高系统性能,减少支持成本,并进行有效的调节。

14. IBM Rational PurifyPlus-帮助开发人员查明C/C++、托管.NET、Java和VB6代码中的性能和可靠性错误。PurifyPlus 将内存错误和泄漏检测、应用程序性能描述、代码覆盖分析等功能组合在一个单一、完整的工具包中。

15. Parasoft Insure++-针对C/C++应用的运行时错误自动检测工具,它能够自动监测C/C++程序,发现其中存在着的内存破坏、内存泄漏、指针错误和I/O等错误。并通过使用一系列独特的技术(SCI技术和变异测试等),彻底的检查和测试我们的代码,精确定位错误的准确位置并给出详细的诊断信息。能作为Microsoft Visual C++的一个插件运行。

16. Compuware DevPartner for Visual C++ BoundsChecker Suite-为C++开发者设计的运行错误检测和调试工具软件。作为Microsoft Visual Studio和C++ 6.0的一个插件运行。

17. Electric Software GlowCode-包括内存泄漏检查,code profiler,函数调用跟踪等功能。给C++和.Net开发者提供完整的错误诊断,和运行时性能分析工具包。

18. Compuware DevPartner Java Edition-包含Java内存检测,代码覆盖率测试,代码性能测试,线程死锁,分布式应用等几大功能模块。

19. Quest JProbe-分析Java的内存泄漏。

20. ej-technologies JProfiler-一个全功能的Java剖析工具,专用于分析J2SE和J2EE应用程序。它把CPU、执行绪和内存的剖析组合在一个强大的应用中。JProfiler可提供许多IDE整合和应用服务器整合用途。JProfiler直觉式的GUI让你可以找到效能瓶颈、抓出内存泄漏、并解决执行绪的问题。4.3.2注册码:A-G666#76114F-1olm9mv1i5uuly#0126

21. BEA JRockit-用来诊断Java内存泄漏并指出根本原因,专门针对Intel平台并得到优化,能在Intel硬件上获得最高的性能。

22. SciTech Software AB .NET Memory Profiler-找到内存泄漏并优化内存使用针对C#,VB.Net,或其它.Net程序。

23. YourKit .NET & Java Profiler-业界领先的Java和.NET程序性能分析工具。

24. AutomatedQA AQTime-AutomatedQA的获奖产品performance profiling和memory debugging工具集的下一代替换产品,支持Microsoft, Borland, Intel, Compaq 和 GNU编译器。可以为.NET和Windows程序生成全面细致的报告,从而帮助您轻松隔离并排除代码中含有的性能问题和内存/资源泄露问题。支持.Net 1.0,1.1,2.0,3.0和Windows 32/64位应用程序。

25. JavaScript Memory Leak Detector-微软全球产品开发欧洲团队(Global Product Development- Europe team, GPDE) 发布的一款调试工具,用来探测JavaScript代码中的内存泄漏,运行为IE系列的一个插件。

 

 

附录:内存泄漏的发生方式

1.     常发性内存泄漏。发生内存泄漏的代码会被多次执行到,每次被执行的时候都会导致一块内存泄漏。

2.     偶发性内存泄漏。发生内存泄漏的代码只有在某些特定环境或操作过程下才会发生。常发性和偶发性是相对的。对于特定的环境,偶发性的也许就变成了常发性的。所以测试环境和测试方法对检测内存泄漏至关重要。

3.     一次性内存泄漏。发生内存泄漏的代码只会被执行一次,或者由于算法上的缺陷,导致总会有一块且仅有一块内存发生泄漏。

4.     隐 式内存泄漏。程序在运行过程中不停的分配内存,但是直到结束的时候才释放内存。严格的说这里并没有发生内存泄漏,因为最终程序释放了所有申请的内存。但是 对于一个服务器程序,需要运行几天,几周甚至几个月,不及时释放内存也可能导致最终耗尽系统的所有内存。所以,我们称这类内存泄漏为隐式内存泄漏。

 

什么是系统资源?

当应用程序在Windows中运行时,Windows必须实时"跟踪"该应用程序的运行,并保留与之相关的许多信息,如按钮、光标、菜单的位置和位图、窗口的状况等,这些信息由Windows保留在一种叫堆的内存块中,堆的英文为Heap。简单地说,堆是采用特殊机制管理的内存块。由Windows的一个系统内核User.exe管理的堆叫做User资源堆(User Resource Heap),由另一个系统内核Gdi.exe管理的堆叫做GDI资源堆(Graphical Device Interface Resource Heap,简称GDI Resource Heap),User资源堆和GDI资源堆合称为系统资源堆(System Resource Heap),习惯上就把它们叫做系统资源(System Resource)。

  微软将Windows的系统资源(堆)分为五个堆,其中User资源堆为三个,而GDI资源堆为两个。

  三个User资源堆分别是:16位的用户堆(User Heap,64KB);32位的窗口堆(Windows Heap,2MB);32位的用户菜单堆(User Menu Heap,2MB)。

  两个GDI资源堆分别是:16位的GDI堆(GDI Heap,64KB);32位的GDI堆(GDI,2MB)。

  从这里的系统资源分类和大小我们应该明白,不管CPU是P4还是486,内存是8M还是1G,所有Windows的用户都拥有同样大小的系统资源(堆),用户不能自已增加或减少系统资源的大小,这是由操作系统决定的,与硬件档次没有任何关系。

  Windows的User资源堆和GDI资源堆的可用(Free)空间称为可用 User资源和可用GDI资源,Windows中以百分数表示它们,用户可以选择 "开始/附件/系统工具/系统信息",来实时查看它们的大小。 
 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

内存溢出(out of memory)和内存泄露(memory leak)的区别和检测工具方法 的相关文章

  • 零基础入门STM32编程(九)——定时器PWM呼吸灯(CUBEMX)

    一 前言 前面章节我们学了如何使用定时器中断点灯 原理为定时器计数达到1s时产生中断 此时单片机调用中断服务函数 执行中断服务函数中的代码 本节我们通过定时器的PWM功能实现呼吸灯的功能 二 定时器PWM功能 2 1 端口复用 定时器的PW
  • 数据挖掘案例实战:利用LDA主题模型提取京东评论数据

    数据挖掘案例实战 利用LDA主题模型提取京东评论数据 网上购物已经成为大众生活的重要组成部分 人们在电商平台上浏览商品和购物 产生了海量的用户行为数据 其中用户对商品的评论数据对商家具有重要的意义 利用好这些碎片化 非结构化的数据 将有利于
  • 3D【10】网格优化:Laplacian Mesh Optimization

    拉普拉斯网格优化与平滑是网格处理的经典算法 其一些基本概念可以作为神经网络预测3D mesh的一些约束 如平滑 我们先来看看一些基本概念 基本概念 首先 我们用 G V E G V E G V E 来表示一个网格 其中 V vT1 vT
  • 如何解决长对话摘要生成问题?

    主要参考论文 DYLE Dynamic Latent Extraction for Abstractive Long Input Summarization 摘要 基于transformer的模型已经在短输入的摘要提取方面取得了先进的性能
  • 数据库系统工程师考点笔记

    目录 第1章 计算机系统知识 1 1 计算机硬件基础知识 1 1 1 1 中央处理单元 1 1 1 2 存储器 4 1 1 3 总线 7 1 1 4 输入输出控制 10 1 2 计算机体系结构 14 1 2 1 CISC和RISC 15 1
  • linux下文件的mtime

    利用find命令按文件修改时间对文件进行清理时 预想中应该被清理的文件没有被清理掉 所以专门测试了下mtime的使用规则 测试时间为 wang wmy test date 2020年 10月 24日 星期六 17 55 50 CST wan
  • mybatie+spring+mvc使用反射遇到的问题

    问题1 使用反射调用 serviceImpl时 使用注解的 Dao对象是空 解决办法在 serviceImpl类中 直接去spring容器获取bean 问题2 在一个类TestServiceImple的方法中 使用事务控制 中调用另外一个类
  • 延锋安道拓:简化工作流程 实现研发数据外发安全可控

    客户简介 延锋安道拓座椅有限公司成立于1997年 是由延锋伟世通汽车饰件系统有限公司 隶属于上汽集团华域汽车SH 600741 和美国江森自控国际有限公司 NYSE JCI 共同投资组建的合资企业 拥有70余家分子公司和2个海外制造基地 为
  • 加密货币市值、股市市值、房地产价值

    加密货币市值 股市市值 房地产价值 全球加密货币市值共0 85万亿美元 统计时间2022年12月6日 比特币 时间2022年12月6日价值0 33万亿美元 其他 时间2022年12月6日价值0 52万亿美元 全球流通货币价值共8万亿美元 统

随机推荐

  • @【 ENVI】“应用程序无法正常启动0x0000007b”问题

    ENVI 应用程序无法正常启动0x0000007b 问题 ENVI5 3 百度网盘 链接 https pan baidu com s 1P1nI9fKEGeNbSsMt9D3mMA 提取码 zely 记得安装目录里面不能有中文 idlrt
  • 无线鼠标计算机不识别,教你笔记本电脑检测不到无线鼠标如何解决

    无线鼠标由于没有线的牵绊 受到很多网友的喜爱 特别是笔记本电脑用户 不过最近有网友说自己的笔记本电脑检测不到无线鼠标怎么办 无线鼠标失灵了 其实这个是很常见的问题 造成的原因也比较多样 下面小编就给大家分享下笔记本电脑识别不了无线鼠标的解决
  • 从零开始学nginx

    1 nginx简介 nginx 发音同engine x 是一款轻量级的Web服务器 反向代理服务器及电子邮件 IMAP POP3 代理服务器 并在一个BSD like协议下发行 nginx由俄罗斯的程序设计师Igor Sysoev所开发 最
  • Ubuntu下如何用命令行运行deb安装包

    如果ubuntu要安装新软件 已有deb安装包 例如 iptux deb 但是无法登录到桌面环境 那该怎么安装 答案是 使用dpkg命令 dpkg命令常用格式如下 sudo dpkg I iptux deb 查看iptux deb软件包的详
  • 有序充电运营管理平台是基于物联网和大数据技术的充电设施管理系统-安科瑞黄安南

    随着我国能源战略发展以及低碳行动的实施 电动汽车已逐步广泛应用 而电动汽车的应用非常符合当今社会对环保意识的要求 以及有效节省化石燃料的消耗 由于其没有污染排放的优点以及政府部门的关注 电动汽车将成为以后出行的重要交通工具 由于大批的电车作
  • openssl AES加密、解密示例代码

    openssl AES加密 解密 关于加密解密后长度的说明 AES 高级加密标准 是一种对称加密算法 它使用相同的密钥进行加密和解密操作 无论是加密还是解密 输入和输出的字节数保持一致 AES算法操作的数据以字节为单位 输入数据被分成16字
  • TensorFlow是什么

    TensorFlow是一个开源的深度学习框架 由Google开发 用于构建和训练神经网络 它提供了一种简单而灵活的方法来构建各种类型的机器学习模型 包括卷积神经网络 循环神经网络 深度神经网络等 TensorFlow使用图和张量的概念来描述
  • Mysql免安装版的root密码是多少

    免安装版的Mysql在初始化后root是没有密码的 1 下载免安装版Mysql 下载链接 MySQL Download MySQL Community Server 下载后解压 里面的目录是这样的 2 添加配置文件和系统环境 在系统变量中添
  • redis bitmap实现签到(包含工具类)

    很多应用比如签到送积分 签到领取奖励 签到 1 天送 10 积分 连续签到 2 天送 20 积分 3 天送 30 积分 4 天以上均送 50 积分等 如果连续签到中断 则重置计数 每月初重置计数 显示用户某个月的签到次数 在日历控件上展示用
  • Spring 基础--第一个spring项目及IOC

    一 第一个spring项目 1 导入Jar包
  • 准备写本书

    立个flag 写本书 关于数字IC物理设计 为了避免半途而废 本人在此立下flag 今天起 两年为期 写一本关于数字IC物理设计的书 初步想法 利用公众号专辑功能 先从小章节写起 然后汇聚成册 请大家监督 本来年初就想写 但是迟迟没下定决心
  • 服务器被爬虫恶意攻击怎么办?

    在有预算的情况可以采购第三方服务防火墙 没钱就使用开源的WAF进行防护 WAF防火墙的基本防护原理 WAF Web 应用防火墙 可以使用多种技术来防止恶意爬虫攻击 例如 1 黑名单 WAF 可以使用黑名单技术来过滤恶意爬虫的请求 黑名单中包
  • 【机器学习】TF-IDF以及TfidfVectorizer

    TF IDF定义 TF IDF 全称为 词频一逆文档频率 TF 某一给定词语在该文档中出现的频率 T F w 词语 w
  • common-lang包中一些工具类的使用说明

    一 common lang包常用的类有 1 StringUtils类 该类主要提供对字符串的操作 对null是安全的 主要提供了字符串查找 替换 分割 去空白 去掉非法字符等等操作 2 ObjectUtils类 主要是对null进行安全处理
  • vs网站 服务器变量,了解下变量赋值 (值 vs 引用)

    理解 JavaScript 如何给变量赋值可以帮助我们减少一些不必要的 bug 如果你不理解这一点 可能很容易地编写被无意中更改值的代码 JavaScript 总是按照值来给变量赋值 这一部分非常重要 当指定的值是 JavaScript 的
  • Qt的信号和槽是如何工作的

    用Qt做过开发的朋友 不知道是否曾为下面这些问题疑惑过 我们知道Qt是基于C 的 Qt写的代码最终还是要由C 编译器来编译 但是我们的Qt代码中有很多C 里没有的关键字 比如slots signals Q OBJECT等 为什么C 编译器会
  • mpvue页面卸载数据不清空

    mpvue有个坑页面卸载了 在小程序层面上是销毁了 但是vue层面页面的实例还在 为了实现再次进入清除数据的效果 可以试一下这个折中的办法 在onload里面清除一下实例中的数据 onLoad e Object assign this th
  • Leaflet使用wfs的示例

    Leaflet是一个开源的Web地图库 可以用来在网站上显示地图 可以使用Leaflet的功能扩展 Leaflet WFS 来在Leaflet地图中使用WFS Web Feature Service 功能 以下是使用Leaflet和Leaf
  • java是值传递还是引用传递

    文章目录 1 前言 2 java是值传递还是引用传递 1 前言 java是值传递 值传递是指在调用方法时将实际参数拷贝一份传递到方法中 这样在方法中如果对参数进行修改 将不会影响到实际参数 当传的是基本类型时 传的是值的拷贝 对拷贝变量的修
  • 内存溢出(out of memory)和内存泄露(memory leak)的区别和检测工具方法

    内存溢出 out of memory 是指程序在申请内存时 没有足够的内存空间供其使用 出现out of memory 比如申请了一个integer 但给它存了long才能存下的数 那就是内存溢出 内存泄露 memory leak 是指程序