内存泄露的检测方法

2023-11-15

本文来自http://blog.csdn.net/lijun84 ,引用必须注明出处!

 

在谈及内存泄漏时,对于没有太多经验的新人来说总是很头疼的一件事。因为如果项目早期没有将其纳入代码框架,后期部署上线之后,仅从进程 crash 的 dump 很难找到线索,即使有最后的调用栈信息也很难下手。

 

本文只想谈谈在各种情况下如何检测内存泄漏,也算给自己这方面的经验做个小结。

 

貌似谈内存泄漏检测目的有些多余。无非就是定位到泄漏点,然后是失误就修改,是自己的内存管理框架问题,那么就考虑改机制。

但仔细想想什么地方才可能是泄漏点,其实这个问题依情况而定还是比较复杂的。因为造成泄漏无非就是分配了但没有释放,可是你不了解软件的架构或结构,你如何知道正确的处理流程是该什么时候释放,在哪释放?

所以通常内存检测会分为 2 个步骤,第一个步骤通常可以工具辅助自动化,而第二个步骤也许必须人工做。

(1)    检测到大量分配而未释放以造成内存大量消耗或耗尽的代码点

(2)    根据代码结构和实现方式发现应该在哪释放,如何释放 (有可能需要改变代码结构)

 

内存泄漏的分类:

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

 

(2)       偶发性内存泄漏。发生内存泄漏的代码只有在某些特定环境或操作过程下才会发生。

 

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

 

(4)       隐式内存泄漏。程序在运行过程中不停的分配内存,但是直到结束的时候才释放内存。

 

内存泄漏的检测形式和阶段:

(1)       架构期纳入:这种情况一般会有自己的内存管理模块,并且有各模块分配 / 释放的追踪机制,且在日志中体现。

优点:

(a)       使内存管理的问题清晰化,更易掌控和全盘布局。

(b)       能尽早发现内存问题。

缺点:

(a)       当项目时间比较紧时,需要花费额外 efforts 。

(b)       追踪机制的代码本身编写要相当谨慎,不能发现泄漏问题。

 

(2)       项目提交前:此阶段可以用一些侵入式检测工具,这类工具代价也比较小,一般加个头文件或加个编译选项什么的就搞定。

优点:代价小,不会影响项目进度,且通常情况下比较有效。

缺点:在些特定情况下不那么有效(如:项目中做了自己的内存管理框架并有一定程度的封装)

 

(3)       项目提交并部署后的运行期:这个阶段基本就是亡羊补牢了。也是最头痛的,救火阶段。此阶段一般限制很多(如:无法替换客户程序并且还原客户部署环境,更甚者连客户端的相应版本代码已没了),那么这时基本只能寄希望于一些动态非侵入式的检测工具了。

      优点:很幸运,你可能有有效的检测工具可用。

缺点:很不幸,可能此类工具限制比较多,甚至无法使用(多数情况如此,因为现在的软件环境已经很庞大很复杂了)。

 

内存泄漏检测方法分类:

(1)       替换接口函数法:

这种方法的思想比较简单,并且大量侵入式的检测工具也是这样做的(其实一些 CRT 都有自带,还有些自带的 malloc 调试库)。替换或重载你的 malloc/new 和 free/delete 函数,并做下面几件事:

(a)    在你成功申请内存后:记录你的当前函数名和代码行和你申请的内存块的地址。

(b)    将以此函数名(模块)下的内存块计数器加 1.

(c)    在申请释放内存前:对比所有函数名(模块)下的已分配内存块地址,找到就将相应计数器减 1.

当然实现思想大致如此,可真正实现是需要一些优化的,比如将函数名或内存地址做 hash ,以便省去搜索消耗。

 

(2)       内存快照对比法:

这种方法不常用,并且效果不太好,但对于以最快的方式发现内存在什么阶段存在泄漏还是比较有效的。

 

(3)       运行期 Hook 法:

这种方法在很多商业工具中常用,单地说,当你的程序开始运行时,它的 DLL 被自动载入进程的地址空间(这可以通过 system-level 的 Hook 实现),然后它会修改进程中对内存分配和释放的函数调用,让这些调用首先转入它的代码,然后再执行原来的代码。实际只是方法 1 的变种。

 

(4)       进程资源监控法:

此方法用于取代方法 2 快速判断是否存在内存泄漏问题时比较有效,可以通过系统自带的 Performance Monitor ,查看内存相关计数的值来快速判断是否存在泄漏。

 

内存泄漏检测工具:

(1)       静态扫描工具: splint, BEAM 等,此类工具可以检测没初始化的变量,废弃的空指针,内存泄漏,冗余计算等潜在问题。但缺点是误报太多。就和编译器的警告一样,你可以重视,但它不一定是引发问题的根源。

 

(2)       动态侵入性工具: mtrace , dmalloc , memwatch , VLD 等 N 多,都是利用堆栈快照 + TAG 的方法。

 

(3)       动态非侵入性工具: BoundsChecker , purify, valgrind, YAMD 等,一般用 Hook 运行库的方法。

 

(4)       资源监控工具: windows 上一般就是 Performance Monitor, linux 可以用 ps 带相应的参数。

 

小结:

虽然上面介绍了那么多种方法,其实内存泄漏发生时往往现场情况更棘手,资源和信息的缺乏还是给解决问题带来了很大难度。

我个人建议如果团队都是新手,没什么和内存打交道经验的话,尽量避免用 C/C++ ,而 . NET 或 Java 也许成本会低很多,维护代价也会小很多。

当然如果种种原因(如客户要求)不得不用,那么最好能考虑用些成熟的 GC 库,如 HP 的 Boehm’s GC.

最后如果客户连第三方库的使用也限制了,那么你在项目早期就要重视内存管理和追踪的问题。

       嘿嘿,如果以上都失效了。也到了最极端的地步,没办法,考验你实力的时候到了,只有 Crack 级调试的经验可以帮助你


本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/lijun84/archive/2011/06/20/6556732.aspx

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

内存泄露的检测方法 的相关文章

  • TPL Dataflow如何删除块之间的链接

    我想知道 如何删除块之间的链接 换句话说 我想要与 LinkTo 相反 我想写一个基于 tlp 数据流的记录器 我编写了这个接口 并希望在需要时删除 ILogListener 的订阅 public interface ILogManager
  • 从变量使用 OLE DB 源命令的 EzAPI 等效项是什么?

    tl dr 使用 来自变量的 SQL 命令 数据访问模式的 OLE DB 源并分配变量的 EzAPI 代码是什么 Preamble 每月一次 我们需要使用生产数据的子集刷新我们的公共测试站点 我们已确定 根据我们的需求 SSIS 解决方案最
  • 创建动态对象

    如何动态创建对象 string columnNames EmpName EmpID PhoneNo List
  • 未定义的参考错误 - rand

    我正在创建一个命令行 C 测试应用程序 可执行 以便在我的 root Android 设备上运行 该可执行文件使用多个预构建的 C 库 其中之一使用 rand 在链接状态期间我收到错误 rand 的未定义引用 为了检查路径是否设置正确 我尝
  • 获取在 Unity 中实现接口的所有类型

    如果您只想知道解决方案 请跳至更新 我有一个应用程序 它使用以下代码来获取并运行许多工作方法 var type typeof IJob var types AppDomain CurrentDomain GetAssemblies Sele
  • 如何在 VS 2013 的立即窗口中执行 LINQ 和/或 foreach?

    在调试过程中探测当前状态时 立即窗口是非常有用的工具 我了解到 通过使用问号 人们可以在那里做更多的事情 如图所示在这篇文章中 https stackoverflow com questions 32934635 execute metho
  • send() 使我的程序崩溃

    我正在运行服务器和客户端 我正在我的计算机上测试我的程序 这是服务器中向客户端发送数据的函数 int sendToClient int fd string msg cout lt lt sending to client lt lt fd
  • 将二维整数作为 Readonly/const 存储在单独的类中,同时保持非公开

    这是我在使用这个地方作为我的 去处 以获取关于什么有效 无效 为什么等的一般意见之后的第一个问题 那么让我们试试这个 由于我的经验有限 我一直在尝试寻找更好的方法来创建固定数据字段 我可以在整个程序中引用这些字段 例如我反复显示的最终用户可
  • MySQL 性能 DELETE 或 UPDATE?

    我有一个超过 10 7 行的 MyISAM 表 向其中添加数据时 我必须在最后更新 10 行 删除它们然后插入新行更快 还是更新这些行更快 应更新的数据不是索引的一部分 索引 数据碎片怎么样 UPDATE到目前为止要快得多 当你UPDATE
  • 重写 ASP.Net Core 中的 415 响应

    在 ASP net Core 2 1 中 我想返回 Json 响应以及状态代码 415 而不是默认返回的 415 为了实现这一点 我使用资源过滤器 public class MediaTypeResouceFilter Attribute
  • mysql查询先慢后快

    我有 2 个 myISAM 表 分别称为 tests 和 completed tests 一个有 170 个条目 另一个有 118k 条目 当我运行此查询时 SELECT ct archive ct status ct score ct u
  • GridView必须添加到表单标签中才能渲染

    TextWriter tr new StringWriter HtmlTextWriter writer new HtmlTextWriter tr HtmlForm form new HtmlForm form Controls Add
  • 在没有诊断的情况下,保守函数中是否会出现显式指定的未定义行为

    脱离评论here https stackoverflow com a 76948726 1013719 3 简介 defs 3 65 defns undef https eel is c draft defns undefined says
  • OpenXML 如何获取范围内的单元格

    请帮助我获取范围内的单元格 例如从 A 1 到 E 11 都是矩形单元格 目前我的理想是 Worksheet worksheet GetWorksheet document sheetName SheetData sheetData wor
  • 什么时候适合在 C++ 中使用 static(在未命名的命名空间上)?

    我一整天都在阅读有关未命名命名空间的文章 大多数文章都解释了何时应该在 static 关键字上使用未命名命名空间 但我仍然有一个大问题什么时候适合使用静态 毕竟它还没有完全弃用 那么带有静态函数的头文件我现在应该将它们放入未命名的命名空间中
  • 解析 SWIG 接口文件的结构属性

    这是我不久前问过的问题的延续 为通过参数返回的函数创建类型映射 https stackoverflow com questions 12793973 create a typemap for a function that returns
  • 在一个数据库请求中连接 IQueryable 集合

    我使用实体框架 我需要连接两个集合 例如 IQueryable
  • 使用 C++20 概念避免 std::function

    过去 当我想要回调作为函数参数时 我通常决定使用std function 在极少数情况下 我绝对从不使用捕获 我使用了typedef改为函数声明 因此 通常我的带有回调参数的声明看起来像这样 struct Socket void on re
  • 是一对一的关系不好的策略

    用户始终拥有一个钱包 一个钱包始终属于一位用户 由于我想分离与钱夹相关的属性 我创建了 Wallet 对象并能够跟踪钱交易 我创建了 public Wallet Entity
  • Microsoft Graph API 调用无限期挂起

    我正在尝试使用 Microsoft Graph 查询 Azure Active Directory 用户信息 我可以很好地进行身份验证 但是当我尝试查询用户信息时client Users我的应用程序无限期挂起 没有超时 没有错误 只是挂起

随机推荐

  • c++ 定时器_「STM32」定时器中断实验

    在上一篇文章中 STM32 定时器概述 中 定时器可以被人为分为4个大部分 时钟发生器 实际模块 输入捕获 输出比较 而定时器中断实验 我们更多的在操作时钟发射器这个模块 这个应用也是定时器最基本的应用了 时钟选择 内部时钟选择 时钟计算方
  • SpringBoot使用@JsonDeserialize和@JsonSerialize注解的功能简介说明

    转自 SpringBoot使用 JsonDeserialize和 JsonSerialize注解的功能简介说明 下文笔者讲述 JsonDeserialize和 JsonSerialize注解的功能简介说明 SpringMVC 在Spring
  • 【SQL基础】【关键字大写】条件查询:比较、不等于、IN、为空、BETWEEN

    概述 1 内容介绍 条件查询 比较 不等于 IN 为空 BETWEEN 2 建表语句 drop table if exists user profile CREATE TABLE user profile id int NOT NULL d
  • 使用 vite 代替 webpack 搭建 react 前端开发环境

    说明 在大型前端项目中 我们一般会使用 webpack Rollup 等工具进行模块整合 但是庞大的代码量会使得我们在开发阶段花费更多的时间在 代码改动 gt 页面渲染 这个阶段 即使使用 HMR 这个问题也没有完全的解决 项目代码量达到一
  • plsql链接服务器无响应,sqlplus 连接数据库无响应

    一批三台安装服务器 先后出现了sqlplus 连接数据库无响应问题 1 因为几乎同一时间出现问题 起初怀疑是网络组对网络有整体调整 后经过确认网络组有调整 但不影响我们的服务器 2 telnet server 1521端口正常响应 3 从终
  • 深度解析,抖音对口型唱歌类短视频内容制作流程,步骤技巧分享

    就像之前分享的信息差案例一样 任何时候都有信息差 但是还有一种叫认知差 就是认知高的人赚认知低的人的钱 不是有句话很火吗 你永远也赚不到认知以外的钱 更多精彩干货请关注共众号 萤火宠 你的认知很高 可以高客单价赚高认知人群的钱 但是也有些人
  • 图形学-改进的Bresenham算法

    图形学 改进的Bresenham算法 原理 代码 原理 虽然中点Bresenham算法是一种效率很高的算法 但也还有改进的余地 当然 其基本原理仍是每次在最大位移方向上走一步 而另一个方向上走还是不走取决于误差项的判断 根据中点Bresen
  • JSP和JavaBean

    8 JSP 8 1 什么是JSP Java Servlet Pages java服务器端页面 也和Servlet一样 用于实现动态Web技术 最大特点 写JSP就像是写HTML 区别 HTML只给用户提供静态的数据 JSP页面中可以嵌入Ja
  • 智慧政务行业发展报告

    转自微信公众号 智慧城市圈子邱文斌 一 智慧政务行业发展状况 从上个世纪90年代开始 政府信息化的建设就开始围绕 通 进行 而现今正逐渐过渡到 云 的建设 从网络的连通 数据的整合 到云的出现与整合 政府信息化的建设是一个漫长而又快速发展的
  • element-ui 实现多日期选择

    一 前端代码
  • Spring 多线程异步上传图片、处理水印、缩略图

    使用环境 SpringBoot FastDfs thumbnailator fdfs环境自己搞吧 thumbnailator maven依赖
  • C++中引用的用法以及将引用作为函数的形参

    在C 中引用就相当于是给变量起了一个别名 有点类似于指针 但是与指针又不同 引用的初始化 int i i 10 变量i的引用 引用必须在创建的时候就要初始化 而指针可以在任意的时候初始化 引用就相当于是给变量起了一个别名 int i r i
  • HTML基本结构

    HTML一般是在vscod中进行书写 后缀为html 其完整的基本结构如下 h1 一级标题 h1 每一个尖括号 lt gt 代表着标签或者说是元素 不同的标签代表有着不同的作用 标签一般成对出现后一个标签为前一个标签加一个 例如 但也有单个
  • 基于巴法云的esp8266实现温湿度、LED、sg90舵机和HC-RS04实现的小程序远程控制

    基于巴法云的esp8266实现温湿度 LED sg90舵机和HC RS04实现的小程序远程控制 具体代码 本项目想法已经在我脑海想了很久了 都没有时间去实现它 这次刚刚考完试就用了两天把它做了出来 希望对大家有帮助 有什么需要的可以在下面留
  • upload-labs:pass-10

    is upload false msg null if isset POST submit if file exists UPLOAD PATH deny ext array php php5 php4 php3 php2 html htm
  • 工厂三兄弟之工厂方法模式(四)

    5 重载的工厂方法 Sunny公司开发人员通过进一步分析 发现可以通过多种方式来初始化日志记录器 例如可以为各种日志记录器提供默认实现 还可以为数据库日志记录器提供数据库连接字符串 为文件日志记录器提供文件路径 也可以将参数封装在一个Obj
  • Puppeteer 安装与注意事项 《一》

    Puppeteer 安装与注意事项 1 安装node js 在使用puppeteer的时候 它一些低版本的node是不支持的 作者推荐使用8以上的版本 否则node在后面使用puppeteer的时候会 抛出 SyntaxError Unex
  • 从外部验证安全密码存储

    许多网站 包括 Adobe Yahoo LinkedIn Gawker等大型网站 不安全地存储用户密码 可以是纯文本格式的 也可以是加密的 可逆的 格式 或者是使用残破或蛮力的哈希函数 许多网站的密码存储机制仍然很差 所以呢 好吧 如果数据
  • js生成柱状图

  • 内存泄露的检测方法

    本文来自http blog csdn net lijun84 引用必须注明出处 在谈及内存泄漏时 对于没有太多经验的新人来说总是很头疼的一件事 因为如果项目早期没有将其纳入代码框架 后期部署上线之后 仅从进程 crash 的 dump 很难