微软Debug CRT库是如何追踪C++内存泄露的?

原文链接:https://blog.csdn.net/CJF_iceKing/article/details/117789677

本人在逛知乎的时候,看到一个问题<<C++不用工具,如何检测内存泄漏?>>, 不乏很多高手的回答。我正好也写了几篇通过工具去分析内存泄露的文章,那先说说工具的方法原理:

    对内存的分配的监测: 记录内存申请时候函数调用栈。一种方法是通过gflag配置让程序在分配内存的时候,记录函数调用栈;还有一种就是通过hook的方式去获取申请内存时候函数调用时候的位置。
    对比程序运行时两个不同时间点的内存分配状况,通过对比找到较多的内存分配点对应的函数调用栈

那么回到正题,如果自己去实现无非就是要实现以上两点。本人正好在上学的时候用过微软 DEBUG CRT库检测过内存泄露,那正好让我们一起再来看看其原理,也正是可以自己去实现的一种方法,要做到知其然知其所以然。
微软Debug CRT库检测C++内存泄露原理?

我们先来解决上述的两个问题。
问题一: 如何获取函数调用栈?

那么你首先要知道什么时候申请了内存?在C++中也就关键字new或者函数malloc,等等。那如何感知到呢?我们知道hook大致可以理解为就是改变原有的函数调用地址,改为你自己实现的函数。是不是有点类似于python中的装饰器了,在自定义的函数内部实现一些逻辑。不过本文要讲的不是hook,而是宏替换。以malloc为例,我们是不是可以通过宏定义,将malloc更改为my_malloc,然后在my_malloc中记录这次内存申请的信息。然后记录的信息要包括:

    申请的内存信息,比如申请的内存状态
    申请内存时候函数调用栈,一般来说可以通过StackWalk获取。不过本文讲解的微软DBUG的CRT库采用的是另外的方式,记录内存申请时候文件名和行号等信息。这样虽然没有函数调用栈精确,但是也基本可以用于定位问题了。

在Visual Studio (本文示例采用Visual Studio 2017)中,选择工程的默认的Debug模式,并且工程配置宏定义_CRTDBG_MAP_ALLOC, 此时将宏定义替换malloc为_malloc_dbg。注意看新的函数会传入文件名字__FILE__和所在行__LINE__

#define malloc(s) _malloc_dbg(s, _NORMAL_BLOCK, __FILE__, __LINE__)

那么malloc做的事情和_malloc_dbg有什么区别呢? 在Release版本中malloc底层其实就直接调用HeapAlloc申请内存(VS2017中)。而_malloc_dbg会申请额外的空间用来做调试用。如下图所示: 在_malloc_dbg中在实际要用的内存UserPtr前面还加了一段_CrtMemBlockHeader用于记录内存申请的相关信息,而No Main's Land部分为一个4个字节填充了0xFDFDFDFD,主要用来校验内存是否溢出或者破坏,这个不是本文的重点。


————————————————
版权声明:本文为CSDN博主「一个程序员的修炼之路」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值