| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> C++知识库 -> CRT内存检测 -> 正文阅读 |
|
[C++知识库]CRT内存检测 |
除了VLD(Visual Leak Detector)、Dr.Memory这些第三方检测工具之外,还可以用vs自带的CRT内存泄漏检测工具来检测内存泄漏。对于MFC工程来说尤其方便,甚至都不需要再手动添加代码,Debug模式下自动开启了CRT检测。 怎么使用我就不废话了,直接去看官方文档: 使用 CRT 库查找内存泄漏 - Visual Studio (Windows) | Microsoft Docs 值得一提的是,它不仅能用于检测内存泄漏,还能用来检测内存越界。 原理对于MFC工程,一般在程序主窗口源文件上会有这么一段:
说白了,CRT检测内存泄漏的方法就是重载了new关键字,每次通过new申请内存,走的都是CRT重载的new方法。重载的new方法最后会走到这个函数:_heap_alloc_dbg_impl
? 检测内存泄漏CRT检测内存泄漏的原理其实很简单,就是使用new申请内存时记录到全局链表中,然后等程序退出时检查链表内还有哪些内存未被释放。 new申请内存,走到_heap_alloc_dbg_impl函数时,会将申请的内存记录到全局链表中:
在程序退出时,调用_CrtDumpMemoryLeaks检测内存泄漏:
?_CrtMemCheckpoint遍历链表,找出所有引用计数大于0的内存块(即未被释放)
CRT的内存泄漏检测机制不是完美无缺的。CRT应该检测不出SysAllocString导致的内存泄漏,因为SysAllocString的内存是由系统分配的,不是通过new申请的。同理,通过malloc申请的内存,如果内存泄漏了,也无法通过CRT检测出来。 检测写内存越界这里只说写越界的原理,一句话总结就是:将内存前后填充为特定值(0xFD),如果写内存之后内存前(后)不再是特定值(0xFD)了,就说明写越界了。 读越界的判断原理我也没空去看源码,无脑猜测是根据起始地址和内存大小判断。 _heap_alloc_dbg_impl申请内存的时候,并不是直接按申请的大小new一块内存返回就算了,而是加了一些东西:
实际申请的内存大小?= sizeof(_CrtMemBlockHeader) + 申请的内存大小 + nNoMansLandSize 也就是说,在内存块前后都加了一点东西,最后判断内存越界靠的就是前后这2块东西。 _CrtMemBlockHeader的结构: nDataSize记录了用户申请的内存大小,gap是整个结构最后4个字节。
nNoMansLandSize的定义:
在用户申请的内存块前面(_CrtMemBlockHeader->gap)和后面(nNoMansLandSize),各有4个字节,用0xFD填充:
那么,如果用户在写内存时越界了,就会覆盖掉前面或者后面4个字节,这一小块内存的内容就不再是0xFD了。因此,我们可以通过判断前后4个字节是否依然是0xFD来判断写内存越界。
例子 HEAP CORRUPTION DETECTED这是我遇到过的一个情况,当时还找了好长时间。报错截图: ? 这个报错是必现的,每次都是在delete一个自定义的Image对象时弹框报错。先说报错原因,Image类是dll导出的类,但是头文件和dll对不上(版本原因),导致new出来的对象内存大小不对,进而导致写内存越界。 参考: “HEAP CORRUPTION DETECTED”错误原因与解决_康康是大神的博客-CSDN博客_heap_corruption
申请的内存大小是5个字节,但是写内存的时候写了6个字节(包含一个结束符)。写越界了可能不会立即报错,delete内存的时候,就发现越界了。参考上文:检测写内存越界 当时百思不得其解,我就new一个Image对象,然后delete就报错了?各种查代码,后来跟踪CRT代码偶然发现delete的内存大小是208,但Image对象的实际大小应该是216,内存大小对不上。 顺着查下去发现了原因,这个Image类是一个dll导出的类,但是头文件和dll对不上了。我使用的头文件的版本比较老,实际上dll的Image类新增了2个int成员,导致头文件和dll的Image对象差了8个字节。更新头文件,重新编译,问题解决。 |
|
C++知识库 最新文章 |
【C++】友元、嵌套类、异常、RTTI、类型转换 |
通讯录的思路与实现(C语言) |
C++PrimerPlus 第七章 函数-C++的编程模块( |
Problem C: 算法9-9~9-12:平衡二叉树的基本 |
MSVC C++ UTF-8编程 |
C++进阶 多态原理 |
简单string类c++实现 |
我的年度总结 |
【C语言】以深厚地基筑伟岸高楼-基础篇(六 |
c语言常见错误合集 |
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 | -2024/11/23 22:14:13- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |