windows内存泄露定位方法
内存泄露(Memory Leak)是C/C++程序经常遇到的一个棘手问题。简单来说,内存泄露就是没有释放本来应该释放的内存。
可以把解决内存泄露问题分成两步,第一步是定位到泄露的堆块,第二步是定位到泄露堆块是哪段代码分配的。本文介绍如何使用CRT堆的调试支持来实现这两个目标。

1._CrtDumpMemoryLeaks
CRT设计了一个名为_CrtDumpMemoryLeaks的函数来检测和报告发生在堆上的内存泄露。

调用后产生类似如下的信息:
线程 0x1c98 已退出,返回值为 0 (0x0)。
Detected memory leaks!
Dumping objects ->
D:\cpp\vs2019\memleak\memleak\memleak.cpp(29) : {87} normal block at 0x00890838, 100 bytes long.
 Data: <                > CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD 
D:\cpp\vs2019\memleak\memleak\memleak.cpp(26) : {86} normal block at 0x008907F8, 20 bytes long.
 Data: <beijing2013     > 62 65 69 6A 69 6E 67 32 30 31 33 00 CD CD CD CD 
Object dump complete.
程序“[14228] memleak.exe”已退出,返回值为 0 (0x0)。

2.何时调用
上面的函数,无论何时调用,都会将当前堆中未是放过的块认为是泄露而转储出来。为了防止把将来能正常释放的块误当作内存泄露,我们必须选择合适的时机来调用这个函数。太早调用,会误判。
何时调用呢?CRT的退出函数(exit 和 doexit)会在执行完终结器(包含全局对象析构)后,再调用_CrtDumpMemoryLeaks
只要设置一个标记就会激活这个函数检查:
_crtDbgFlag |= _CRTDBG_LEAK_CHECK_DF;

3.定位导致泄露的源码
定义一个标记_CRTDBG_MAP_ALLOC
#define _CRTDBG_MAP_ALLOC
#include <crtdbg.h>

注意顺序不能错,这个标记影响crtdbg.h的编译,从而影响malloc的函数定义。
这样处理后,malloc就可以打印行号了,但new还不行。

需要定义调试版本的new 
#ifdef _DEBUG
#define MYDEBUG_NEW   new( _NORMAL_BLOCK, __FILE__, __LINE__)
#define new MYDEBUG_NEW
#endif// _DEBUG

这样就可以打印完整了。

4.快速找到泄露
观察转储打印:
D:\cpp\vs2019\memleak\memleak\memleak.cpp(26) : {86} normal block at 0x008907F8
其中的{86} 代表第86次分配内存操作发生了泄露,你可能要说,我只new过一次,怎么会是第86次?这很容易理解,其他的内存申请操作在C的初始化过程调用的呗。:)
有没有可能,我们让程序运行到第52次内存分配操作的时候,自动停下来,进入调试状态?所幸,crtdbg确实提供了这样的函数:即 long _CrtSetBreakAlloc(long nAllocID)。我们加上它:
_crtBreakAlloc = 86;
这只这个全局变量即可。

你发现,程序运行到 p1 = (char*)new char[20]; 一句时,自动停下来进入调试状态。细细体会一下,你可以发现,这种方式你获得的信息远比在程序退出时获得文件名及行号有价值得多。因为报告泄漏文件名及行号,你获得的只是静态的信息,然而_CrtSetBreakAlloc则是把整个现场恢复,你可以通过对函数调用栈分析(我发现很多人不习惯看函数调用栈,如果你属于这种情况,我强烈推荐你去补上这一课,因为它太重要了)以及其他在线调试技巧,来分析产生内存泄漏的原因。通常情况下,这种分析方法可以在5分钟内找到肇事者。

当然,_CrtSetBreakAlloc要求你的程序执行过程是可还原的(多次执行过程的内存分配顺序不会发生变化)。这个假设在多数情况下成立。不过,在多线程的情况下,这一点有时难以保证。

5. 程序源码:--来自软件调试这本书
#include <stdio.h>
#include <string.h>
#define _CRTDBG_MAP_ALLOC
#include <crtdbg.h>
#include <malloc.h>

#ifdef _DEBUG
#define MYDEBUG_NEW   new( _NORMAL_BLOCK, __FILE__, __LINE__)
#define new MYDEBUG_NEW
#endif// _DEBUG

#pragma warning(disable : 4996)

int main()
{
    char* p1, * p2;
    printf("Sample to demo memory leak checking of RTC by Raymond!\n");

_crtDbgFlag |= _CRTDBG_LEAK_CHECK_DF;
    _crtBreakAlloc = 86;

p1 = (char*)new char[20];
    strcpy(p1, "beijing2013");

p2 = (char*)malloc(100);

return 0;

}

windows内存泄露定位方法相关推荐

  1. 一种定位内存泄露的方法(Linux)

    2019独角兽企业重金招聘Python工程师标准>>> 目的: 本文是<一种定位内存泄露的方法(Solaris)>对应的Linux版本,调试器使用gdb.主要介绍实例部分 ...

  2. android native 代码内存泄露 定位方案

    android native 代码内存泄露 定位方案 java代码的内存定位,暂时我们先不关注.此篇文章,主要围绕c c++代码的内存泄露. ** *欢迎留言,交流您所使用的内存泄露定位方案.*c   ...

  3. 哪些操作会造成内存泄漏及Js内存泄露解决方法

    1.垃圾回收器定期扫描对象,并计算引用了每个对象的其他对象的数量.如果一个对象的 引用数量为 0(没有其他对象引用过该对象),或对该对象的惟一引用是循环的,那么该对象的 内存即可回收 2.setTim ...

  4. vs内存泄露检测方法

    方法一. 1.头文件: #define _CRTDBG_MAP_ALLOC #include <stdlib.h> #include <crtdbg.h>  注意  #incl ...

  5. windows 内存泄露和资源泄漏调试

    AQTime (有x64.win32的)进行内存泄露和资源泄漏监控 http://wenku.baidu.com/view/9aa1c2afdd3383c4bb4cd2c1.html x64下载:ht ...

  6. C++ 内存泄露处理方法 (转)

    1.可以显示内存泄露情况,但无法找到具体的文件位置写法 包含头文件#include <crtdbg.h> 然后在需要检测内存泄露的位置加上语句 _CrtDumpMemoryLeaks(); ...

  7. Linux下内存泄漏定位方法

    Linux下内存泄漏可分为用户空间的内存泄漏和内核空间的内存泄漏. 用户空间内存泄漏的查找方法: 第一步,查找内存泄漏的应用程序. 首先,写一个简单的内存泄漏程序(每秒钟泄漏4MB)umemleak. ...

  8. Android 解决handler内存泄露的方法

    文章目录 1.简介 2.方法一避免Handler 泄露 3.方法二添加弱连接 1.简介 大体理解为: Handler 在使用的时候一般要依附于一个对象,很多时候 handler 延时发送的时候 ,所依 ...

  9. 关于windows内存泄露思考

    如图电脑物理内存16G,在开机不久后,分页缓冲池会增加到N个G,实际没有使用,但却内存加速球爆红. 这就是典型的内存泄露,原因 服务.驱动.应用程序: 1.win r,msconfig,隐藏微软服务, ...

最新文章

  1. 剑指offer:面试题14- II. 剪绳子 II
  2. 【Harvest源码分析】GetF0CandidateContour函数
  3. 【Go语言】【12】GO语言的结构体
  4. 数据安全审查综合解读|如何从被动合规到主动战略风控?
  5. 分享个INNO打包Windows应用程序完整实例脚本(转载)
  6. mysql存储过程打不开了_请问mysql存储过程的问题,我找了几个例子一个都运行不起来,...
  7. 【Python7】csv/excel/matplotlib,排序/树遍历,线/进程,文件/xml操作,百度人脸API,aiohttp/hal/restful/curl
  8. java 设计模式 示例_Java中的中介器设计模式-示例教程
  9. 最美的十大精典爱情句子
  10. 计算机硬件能够直接识别的语言是英语,计算机硬件能直接识别、执行的语言是()...
  11. 低温linux内核启动readl,Linux内核启动流程分析(一)
  12. 晚安,2017。你好,2018。
  13. 数据结构 树的遍历(递归遍历练习)
  14. android接支付宝授权和支付功能
  15. API开创基底细胞癌手术切缘采集,改善过度医疗现状
  16. 3dmax蒙皮详细教程
  17. PBRT的scene.pbrt使用方法
  18. Markdown 中设置图片图注
  19. 日系P2P原理探究(一) — Winny元祖: Freenet
  20. 计算机博士专业学位,计算机博士

热门文章

  1. 洛谷oj题单【入门1】顺序结构-入门难度(Java)
  2. Linux玩国服FF14(最终幻想14)
  3. Linux基础入门(常用指令总结)
  4. 捷联惯导基础知识解析之一(姿态表示方法基础知识)
  5. matlab进行fft仿真,基于fft算法的MATLAB仿真
  6. 3个月Java速成记,一文记录Java学习过程
  7. chrome 出现:Your connection is not private NET::ERR_CERT_WEAK_SIGNATURE_ALGORITHM
  8. Windows内核--驱动程序和内核(1.6)
  9. VideoPlayer的方法机翻
  10. 微软配置outlook服务器,Microsoft Outlook 2013企业邮箱设置教程(POP3)