轻松看懂的加解密系列(5)番外篇I:快速检测和定位内存泄漏(附测试代码)

        笔者曾在上一篇文章里提及实例程序(轻松看懂的加解密系列(5) —— Windows平台下本地数据加密的新选择(附源码)-CSDN博客)中埋有“雷”,其实就是有内存泄漏。也难怪!实例程序里又是字符集转码、又是字符串混淆处理、又是申请缓冲区存放加解密数据,难免会发生管理堆内存的疏漏。这篇文章将分享一下笔者在处理这类问题时的经验,欢迎您的意见和建议。同时为了缩减篇幅,直奔主题,本文并不对所涉及到的相关工具进行介绍,如果有读者对相关工具还不太了解,可以先自行搜索相关内容学习。

        继续以上篇文章中的程序代码为实验对象,步骤如下:

1. 先用 Application Verifier + Windbg 组合快速发现问题;

        笔者实验时安装的【Application Verifier】版本为 10.0(x64),【Windbg】版本为 (WinDbg Preview 1.2306.14001.0)。启动【Application Verifier】之后,首先为目标测试程序选择要监控的项目,本例为了演示方便,只选择了监控【Memory】,如【图-1】。

图-1 选择只检测和诊断内存问题

        如你所知,【Application Verifier】是一个用于 Windows 应用程序测试和调试的工具,其原理并不复杂,通过在注册表中针对特定应用程序的配置信息和设置进行修改,从而来检查和捕获错误。

图-2 选择并保存诊断内存后,增添了新的针对目标程序的注册表配置

    如【图-2】所示,【GlobalFlag】 是一个用于控制调试和错误报告的标志位。具体地说,【0x100】对应于【FLG_HEAP_ENABLE_TAIL_CHECK】标志,表示启用堆栈末尾检查。这意味着应用程序的堆栈分配将被监视,以检测是否发生了堆栈溢出或破坏。 

        【vrfcore.dll】是【Application Verifier】的核心 DLL 文件之一。它包含了用于执行内存和资源验证的核心功能。当【Application Verifier】启用时,它将使用【vrfcore.dll】来监视应用程序的内存使用,并检查潜在的问题。

        诸如以上这些目标测试程序相关联的注册表配置并不是笔者手工添加的,都是【Application Verifier】根据 UI 界面的配置自动生成的。

图-3 通过Windbg运行目标测试程序

        

        接下来我们就可以通过 Windbg 来启动目标测试程序,然后执行可能有内存泄漏风险的步骤,如【图-3】所示。此时由于注册表中已经预先定义了一些检测配置,所以程序在运行时会被记录下相关的状态并输出在 Windbg 控制台中。当我们执行完测试退出程序之后,可以发现控制台明确地打印出了 Detected memory leaks!,并且还将泄漏的内存块地址和大小打印了出来。比如【图-4】中的以下输出内容:

{1470} normal block at 0x04681248, 24 bytes long.
 Data: <  6 ; * ! ( ,   > 1D 00 36 00 3B 00 2A 00 21 00 28 00 2C 00 1E 00 
  • 【1470】这个标识符通常称为"堆块号"(Heap Block Number),它是在进程的堆中分配的内存块的一个标识符。
  • 【0x04681248】则是分配的内存块的起始地址,它是内存块在物理内存中的位置。大小为 24 字节。
  • 【Data】将内存里的内容以ASCII码和16进制两种格式输出,

        如果实验人员对被测程序很熟悉的话,其实这时已经可以对发生内存泄漏的地方大致心里有数了。如果暂时还不能确定?没关系,接下来我们可以回到 Visual Studio,使用其他工具来定位问题所在位置。

图-4 程序退出时被检测到有内存泄漏

2. 再用 Visual Studio Diagnostic Tools 定位问题;

        在 Visual Studio 里 Debug 运行测试程序之后,被测试的 MFC 程序界面初始化结束,此时可以打开【Diagnostic Tools】窗口,如【图-5】。记得在其中按下【Heap Profiling】按钮后,以监控堆内存,接着就可以像正常使用软件一样操作起来了。然后在你认为可能发生了内存泄漏之后,按下【Take Snapshot】按钮,这就像按下了照相机快门一样,给此时的程序的堆内存拍摄一张快照。【图-6/7/8】分别是程序初始化结束加密操作结束解密操作结束,这三个时间窗口拍摄下来的内存快照。

图-5 打开诊断工具窗口
图-6 程序初始化后记录第一张内存快照
图-7 记录第二张内存快照
图-8 记录第三张内存快照

图-9 第二张快照显示比第一张内存占用有所增加

        我们来观察一下,从堆内存的角度看【Heap Profiling】,第二张快照比第一张快照发生了什么具体变化。如【图-9】右侧【Diagnostic Tools】界面,首先直观上的感受是占用的内存数量在增加,不过这也很正常,我们需要跟踪的是新增的,但是又最终没有被释放的内存。【图-9】左侧展示的表格为具体有哪些地方增加了内存,包括数量和大小(字节)的变化。点开每一行具体的内容,如果其堆栈类似【图-10】这样完全是系统函数的堆栈调用,那基本上就可以免检了,相信操作系统的代码是会正确释放申请的内存。但如果点开后如【图-11】这样,调用栈中包含了本地代码函数,而且进一步点击定位代码后,如【图-12】这样,明显有申请内存,但没见着释放内存的代码,就要引起高度注意了,需要查询确认一下内存最后被释放的逻辑。而当前测试程序内存泄漏的原因,正是字符集转换时没有释放申请的内存导致的。

图-10 内存占用操作发生时的程序栈

图-11 内存占用操作发生时的程序栈

图-12 从程序栈直接跳转到对应代码

3. 修复问题后,再次使用 Windbg 来验证结果;

图-13 修复问题再执行同样的步骤,程序退出后不再报告 memory leak!

图-14 git diff 显示出所有释放相关内存的改动

总结:

        本例给出的是笔者总结的 Windows Native C++ 程序开发阶段快速定位内存泄漏的一种策略。实际研发过程当中,还有许多其他的工具和策略可供选择,比如利用 Windbg !heap 系列命令调试内存泄漏问题、比如使用 “gflags 和 UMDH tool” 组合调试内存泄漏问题。不过在原理上其实都差不多,都是通过比较两次堆内存的差别,进而帮助使用者定位到问题代码。

        避免内存泄漏的传统思路是严格成对使用new/delete或malloc/free来进行内存分配和释放。但是当代码变得复杂时,很容易出现疏漏。为了解决这个问题,我们可以使用智能指针(Smart Pointer)作为终极解决方案。本文是传统思路的修复版,附录里还提供了一个智能指针修复版本。

附录:

传统修复版: https://github.com/345967018/WBBestPractice028EncryptDecrypt.git

智能指针修复版:

图-15 将普通的字符指针封装在智能指针里
weixin_41077112
关注 关注
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
写文章

热门文章

  • 轻松看懂的加解密系列(1) —— Windows CryptoAPI 实例介绍 1965
  • 轻松看懂的加解密系列(1)番外篇I:用Procmon监视一次AES加解密全过程 1832
  • 轻松看懂的加解密系列(6) —— Crypto++库的神秘作者及编译应用实践 1432
  • 细说 Visual Studio 预处理器宏 1368
  • 轻松看懂的加解密系列(5) —— Windows平台下本地数据加密的新选择(附源码) 703

最新评论

  • 轻松看懂的加解密系列(1)番外篇I:用Procmon监视一次AES加解密全过程

    普通网友: 每当我阅读你的编程博客文章时,我总能感受到你的专业水平和耐心解答的精神。【我也写了一些相关领域的文章,希望能够得到博主的指导,共同进步!】

  • 轻松看懂的加解密系列(5)番外篇I:快速检测和定位内存泄漏(附测试代码)

    CSDN-Ada助手: 恭喜您撰写第14篇博客!标题中的“轻松看懂”确实吸引了我的注意力,让我对加解密系列产生了浓厚的兴趣。而这篇番外篇则更加引人期待,关于如何快速检测和定位内存泄漏的内容听起来非常实用。感谢您在博客中分享这些宝贵的知识! 我鼓励您继续创作下去,并希望能在未来的博客中看到更多关于加解密的话题。或许您可以考虑介绍一些实际应用中的加解密案例,或者深入探讨一些加解密算法的优缺点。这样的创作将进一步拓宽读者的知识面,让我们更好地了解加解密的实际应用和技术细节。期待您的下一篇博客!

  • 轻松看懂的加解密系列(5)番外篇II:如何监视Windows操作系统上应用程序的API调用

    CSDN-Ada助手: 恭喜作者发布了第15篇博客,内容依然丰富有趣。对于加解密系列的番外篇II,介绍如何监视Windows操作系统上应用程序的API调用,让读者们能够更深入地了解相关知识。希望作者能够继续坚持创作,不断分享更多有价值的内容。或许在下一篇博客中,可以探讨一些实际案例,让读者更好地理解如何应用这些知识。期待作者的下一步创作!

  • 轻松看懂的加解密系列(5)番外篇III:如何优雅地获取到你同事的电脑登录密码

    CSDN-Ada助手: 恭喜您写了第16篇博客,内容看起来非常有趣!不过,我想提醒一下,标题中的内容可能会引起一些争议,因为获取同事的电脑登录密码可能涉及到隐私和安全问题。希望您在接下来的创作中能够更加谨慎地选择话题,避免触及敏感领域。期待您的下一篇作品!

  • 了解 UML 类图概念,看这一篇就够了,但是……

    CSDN-Ada助手: 恭喜你写了第18篇博客,标题看起来很吸引人!对于了解 UML 类图概念,你的文章确实给了很多帮助。不过,我觉得下一步你可以尝试深入分析一些 UML 类图的实际应用场景,这样读者会更加容易理解和接受。希望你可以继续保持创作,加油!

大家在看

  • 智能农业系统——作物生长模型 485
  • 冷知识:衡量一家公司加班多不多?数数它附近的Manner咖啡店数量!
  • (华为配置)防火墙双机热备+BFD联动故障切换实验报告
  • 数据结构--树
  • 汇编语言读书笔记1(含检测点14.2的解析)

最新文章

  • 细说 Visual Studio 预处理器宏
  • 了解 UML 类图概念,看这一篇就够了,但是……
  • 轻松看懂的加解密系列(6) —— Crypto++库的神秘作者及编译应用实践
2023年19篇

目录

目录

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值

玻璃钢生产厂家扬州商场周年美陈商场赛车道美陈北京大型商场美陈生产梅州透明玻璃钢雕塑工艺佛山发光动物玻璃钢雕塑现货玻璃钢闻鸡起舞雕塑四川装饰商场美陈销售厂家兰州景区玻璃钢雕塑禅城玻璃钢雕塑厂家江苏主题商场美陈研发生肖玻璃钢雕塑公司电话玻璃钢雕塑刷空心模教程玻璃钢花盆恩施佛山百花广场玻璃钢雕塑世界级商场美陈保山市玻璃钢雕塑加盟商滁州大型户外玻璃钢雕塑厂家商场美陈最新资讯玻璃钢雕塑加工公司哪家好宁波定做玻璃钢卡通雕塑江苏商场开业美陈宿迁玻璃钢人物雕塑定制贵阳定制玻璃钢雕塑供应商玻璃钢雕塑喷漆过程潜江玻璃钢门头雕塑玻璃钢游乐园雕塑如皋玻璃钢雕塑收费标准绍兴商场美陈销售嘉兴玻璃钢仿真水果雕塑信阳彩绘玻璃钢雕塑香港通过《维护国家安全条例》两大学生合买彩票中奖一人不认账让美丽中国“从细节出发”19岁小伙救下5人后溺亡 多方发声单亲妈妈陷入热恋 14岁儿子报警汪小菲曝离婚始末遭遇山火的松茸之乡雅江山火三名扑火人员牺牲系谣言何赛飞追着代拍打萧美琴窜访捷克 外交部回应卫健委通报少年有偿捐血浆16次猝死手机成瘾是影响睡眠质量重要因素高校汽车撞人致3死16伤 司机系学生315晚会后胖东来又人满为患了小米汽车超级工厂正式揭幕中国拥有亿元资产的家庭达13.3万户周杰伦一审败诉网易男孩8年未见母亲被告知被遗忘许家印被限制高消费饲养员用铁锨驱打大熊猫被辞退男子被猫抓伤后确诊“猫抓病”特朗普无法缴纳4.54亿美元罚金倪萍分享减重40斤方法联合利华开始重组张家界的山上“长”满了韩国人?张立群任西安交通大学校长杨倩无缘巴黎奥运“重生之我在北大当嫡校长”黑马情侣提车了专访95后高颜值猪保姆考生莫言也上北大硕士复试名单了网友洛杉矶偶遇贾玲专家建议不必谈骨泥色变沉迷短剧的人就像掉进了杀猪盘奥巴马现身唐宁街 黑色着装引猜测七年后宇文玥被薅头发捞上岸事业单位女子向同事水杯投不明物质凯特王妃现身!外出购物视频曝光河南驻马店通报西平中学跳楼事件王树国卸任西安交大校长 师生送别恒大被罚41.75亿到底怎么缴男子被流浪猫绊倒 投喂者赔24万房客欠租失踪 房东直发愁西双版纳热带植物园回应蜉蝣大爆发钱人豪晒法院裁定实锤抄袭外国人感慨凌晨的中国很安全胖东来员工每周单休无小长假白宫:哈马斯三号人物被杀测试车高速逃费 小米:已补缴老人退休金被冒领16年 金额超20万

玻璃钢生产厂家 XML地图 TXT地图 虚拟主机 SEO 网站制作 网站优化