.NET 桌面软件内存泄露分析
admin
2024-03-23 23:54:10
0

WinDbg 分析

1. 托管还是非托管泄露

这是我们首先就要做出的抉择,可以使用 !address -summary & !eeheap -gc 来定位一下。

0:000> !address -summary--- Usage Summary ---------------- RgnCount ----------- Total Size -------- %ofBusy %ofTotal
Free                                   1311     7ffc`e2b37000 ( 127.988 TB)           99.99%
                              4799        2`4f798000 (   9.242 GB)  74.19%    0.01%
Heap                                   3029        0`906fe000 (   2.257 GB)  18.12%    0.00%
Image                                  3435        0`2b530000 ( 693.188 MB)   5.43%    0.00%
Stack                                   226        0`11e00000 ( 286.000 MB)   2.24%    0.00%
Other                                    90        0`0025c000 (   2.359 MB)   0.02%    0.00%
TEB                                      75        0`00096000 ( 600.000 kB)   0.00%    0.00%
PEB                                       1        0`00001000 (   4.000 kB)   0.00%    0.00%--- Type Summary (for busy) ------ RgnCount ----------- Total Size -------- %ofBusy %ofTotal
MEM_PRIVATE                            7990        2`e6964000 (  11.603 GB)  93.14%    0.01%
MEM_IMAGE                              3445        0`2b536000 ( 693.211 MB)   5.43%    0.00%
MEM_MAPPED                              220        0`0b61f000 ( 182.121 MB)   1.43%    0.00%--- State Summary ---------------- RgnCount ----------- Total Size -------- %ofBusy %ofTotal
MEM_FREE                               1311     7ffc`e2b37000 ( 127.988 TB)           99.99%
MEM_COMMIT                             8158        1`cf52a000 (   7.239 GB)  58.11%    0.01%
MEM_RESERVE                            3497        1`4df8f000 (   5.218 GB)  41.89%    0.00%0:000> !eeheap -gc
Number of GC Heaps: 1
generation 0 starts at 0x0000023ba303e940
generation 1 starts at 0x0000023ba2ebd0d0
generation 2 starts at 0x00000239a80f1000
ephemeral segment allocation context: none
...
Large object heap starts at 0x00000239b80f1000segment             begin         allocated              size
00000239b80f0000  00000239b80f1000  00000239bfe174a8  0x7d264a8(131228840)
0000023a6f050000  0000023a6f051000  0000023a73780800  0x472f800(74643456)
Total Size:              Size: 0xea9878f8 (3935860984) bytes.
------------------------------
GC Heap Size:            Size: 0xea9878f8 (3935860984) bytes.

从中的 MEM_COMMITGC Heap Size 这两个指标来看,主要还是托管内存泄露,虽然非托管内存也不小,大概率还是托管这边导致的,有了这些信息之后,后面就是看下 托管堆 到底都是些什么对象。

0:000> !dumpheap -stat
Statistics:MT    Count    TotalSize Class Name
...
00007ffa2d7a1080  4923008    118152192 System.WeakReference
00007ffa2d725e70  2224022    125834760 System.Object[]
00007ffa2701de10  1044218    133659904 System.Windows.Documents.Paragraph
00007ffa2706b470  1045023    142123128 System.Windows.Documents.Run
00007ffa2706a9b0  2098480    151090560 System.Windows.Documents.TextTreeTextNode
00007ffa2d7267d0  1138661    159949302 System.Char[]
00007ffa2d7259c0  1231039    160962948 System.String
00007ffa29580cd8      214    165608376 MS.Internal.WeakEventTable+EventKey[]
00007ffa2d729750  2116556    169324480 System.Collections.Hashtable
00007ffa2d724478  2117718    209740224 System.Collections.Hashtable+bucket[]
00007ffa2706eb08  4175733    367464504 System.Windows.Documents.TextTreeTextElementNode
00007ffa2700ca48  2088016    384194944 System.Windows.ResourceDictionary
00007ffa2957fdc8  2344569    405666920 System.Windows.EffectiveValueEntry[] 

从中的 TotalSize 来看并没有明显的特征,但从 Count 看还是有一些蛛丝马迹的,比如 System.Windows.Documents.TextTreeTextElementNode 对象为什么高达 417w ? 为什么 System.Windows.Documents.TextTreeTextNode209w ? 虽然都是 WPF 框架的内部类,但从名字上看貌似和 文本类 控件有关系。

2. TextTreeTextElementNode 为什么没被回收

有了这些可疑信息,接下来就需要看下他们为什么没有被 GC 收掉?要想找到答案就需要抽几个 TextTreeTextElementNode 看下用户根是什么?可以使用 !dumpheap -mt xxx 找到 address 之后再用 !gcroot 观察一下。

0:000> !dumpheap -mt 00007ffa2706eb08Address               MT     Size
00000239a815f028 00007ffa2706eb08       88
00000239a815f080 00007ffa2706eb08       88     
00000239a815f2e8 00007ffa2706eb08       88     
00000239a815f340 00007ffa2706eb08       88     
00000239a8259f18 00007ffa2706eb08       88  
...0:000>  !gcroot 0000023a637180e0!gcroot 0000023a637180e0
Thread e6c:000000aebe7fec20 00007ffa296c0298 System.Windows.Threading.Dispatcher.GetMessage(System.Windows.Interop.MSG ByRef, IntPtr, Int32, Int32)rsi: ->  00000239a8101688 System.Windows.Threading.Dispatcher->  0000023b4630e9a8 System.EventHandler->  0000023b4630a990 System.Object[]->  00000239a8425648 System.EventHandler

大多是 TextTreeTextElementNode 和 TextTreeFixupNode 之间的交叉引用,还得耐点心慢慢往上翻,看看可有什么蛛丝马迹,经过仔细排查,发现有一个 RickTextBox 控件
从源码看,在项目中实现了一个自定义的 RichTextBox 控件来实现日志记录,内存泄露问题应该就在这里。

相关内容

热门资讯

linux入门---制作进度条 了解缓冲区 我们首先来看看下面的操作: 我们首先创建了一个文件并在这个文件里面添加了...
C++ 机房预约系统(六):学... 8、 学生模块 8.1 学生子菜单、登录和注销 实现步骤: 在Student.cpp的...
A.机器学习入门算法(三):基... 机器学习算法(三):K近邻(k-nearest neigh...
数字温湿度传感器DHT11模块... 模块实例https://blog.csdn.net/qq_38393591/article/deta...
有限元三角形单元的等效节点力 文章目录前言一、重新复习一下有限元三角形单元的理论1、三角形单元的形函数(Nÿ...
Redis 所有支持的数据结构... Redis 是一种开源的基于键值对存储的 NoSQL 数据库,支持多种数据结构。以下是...
win下pytorch安装—c... 安装目录一、cuda安装1.1、cuda版本选择1.2、下载安装二、cudnn安装三、pytorch...
MySQL基础-多表查询 文章目录MySQL基础-多表查询一、案例及引入1、基础概念2、笛卡尔积的理解二、多表查询的分类1、等...
keil调试专题篇 调试的前提是需要连接调试器比如STLINK。 然后点击菜单或者快捷图标均可进入调试模式。 如果前面...
MATLAB | 全网最详细网... 一篇超超超长,超超超全面网络图绘制教程,本篇基本能讲清楚所有绘制要点&#...
IHome主页 - 让你的浏览... 随着互联网的发展,人们越来越离不开浏览器了。每天上班、学习、娱乐,浏览器...
TCP 协议 一、TCP 协议概念 TCP即传输控制协议(Transmission Control ...
营业执照的经营范围有哪些 营业执照的经营范围有哪些 经营范围是指企业可以从事的生产经营与服务项目,是进行公司注册...
C++ 可变体(variant... 一、可变体(variant) 基础用法 Union的问题: 无法知道当前使用的类型是什...
血压计语音芯片,电子医疗设备声... 语音电子血压计是带有语音提示功能的电子血压计,测量前至测量结果全程语音播报࿰...
MySQL OCP888题解0... 文章目录1、原题1.1、英文原题1.2、答案2、题目解析2.1、题干解析2.2、选项解析3、知识点3...
【2023-Pytorch-检... (肆十二想说的一些话)Yolo这个系列我们已经更新了大概一年的时间,现在基本的流程也走走通了,包含数...
实战项目:保险行业用户分类 这里写目录标题1、项目介绍1.1 行业背景1.2 数据介绍2、代码实现导入数据探索数据处理列标签名异...
记录--我在前端干工地(thr... 这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助 前段时间接触了Th...
43 openEuler搭建A... 文章目录43 openEuler搭建Apache服务器-配置文件说明和管理模块43.1 配置文件说明...