记一次 .NET某账本软件 非托管泄露分析

news2024/11/16 16:27:36

一:背景

1. 讲故事

中秋国庆长假结束,哈哈,在老家拍了很多的短视频,有兴趣的可以上B站观看:https://space.bilibili.com/409524162 ,今天继续给大家分享各种奇奇怪怪的.NET生产事故,希望能帮助大家在未来的编程之路上少踩坑。

话不多说,这篇看一个.NET程序集泄露导致的CLR私有堆泄露的案例,这个泄露和 JsonConvert 有关,哈哈,相信你肯定比较惊讶!

二:WinDbg 分析

1. 到底是哪里的泄露

首先观察一下进程的提交内存的大小,即通过 !address -summary 观察。


0:000> !address -summary
--- Usage Summary ---------------- RgnCount ----------- Total Size -------- %ofBusy %ofTotal
Free                                    390     7dfa`63fa8000 ( 125.978 TB)           98.42%
<unknown>                             13628      205`32974000 (   2.020 TB)  99.92%    1.58%
Heap                                   8143        0`4042b000 (   1.004 GB)   0.05%    0.00%
Stack                                   186        0`1f8e0000 ( 504.875 MB)   0.02%    0.00%
Image                                  1958        0`09775000 ( 151.457 MB)   0.01%    0.00%
Other                                     9        0`001d7000 (   1.840 MB)   0.00%    0.00%
TEB                                      62        0`0007c000 ( 496.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_MAPPED                              312      200`00a06000 (   2.000 TB)  98.92%    1.56%
MEM_PRIVATE                           21717        5`91ecd000 (  22.280 GB)   1.08%    0.02%
MEM_IMAGE                              1958        0`09775000 ( 151.457 MB)   0.01%    0.00%

--- State Summary ---------------- RgnCount ----------- Total Size -------- %ofBusy %ofTotal
MEM_FREE                                390     7dfa`63fa8000 ( 125.978 TB)           98.42%
MEM_RESERVE                            4509      205`0fc14000 (   2.020 TB)  99.89%    1.58%
MEM_COMMIT                            19478        0`8c434000 (   2.192 GB)   0.11%    0.00%

当前的提交内存占用了 2.19G,进程堆占用 1G ,差不多占了一半,但不能说明就是非托管内存泄露,接下来继续观察下托管堆。


0:000> !eeheap -gc
Number of GC Heaps: 8
------------------------------
Heap 7 (000001C4971013A0)
generation 0 starts at 0x000001C817D201A0
generation 1 starts at 0x000001C817C878D8
generation 2 starts at 0x000001C817261000
ephemeral segment allocation context: none
         segment             begin         allocated              size
000001C817260000  000001C817261000  000001C819013F98  0x1db2f98(31141784)
Large object heap starts at 0x000001C907261000
         segment             begin         allocated              size
000001C907260000  000001C907261000  000001C907261018  0x18(24)
Pinned object heap starts at 0x000001C987261000
000001C987260000  000001C987261000  000001C9872ABA50  0x4aa50(305744)
Heap Size:       Size: 0x1dfda00 (31447552) bytes.
------------------------------
GC Heap Size:    Size: 0xba26488 (195191944) bytes.

从卦中可以看到当前的托管堆占用仅 195M,这就更好的验证当前确实存在非托管内存泄露,由于非托管内存没有开启 ust,也没有 perfview 的etw文件,所以没有好的方式进一步挖掘,到这里可能就止步不前了。

2. 到底是哪里的泄露

在 C# 所处的 Windows 进程中,其实有很多的堆,比如:crt堆,ntheap堆,gc堆,clr私有堆,堆外(VirtualAlloc),调试没有标准答案,不断的假设,试探,摸着石头过河,言外之意就是这个堆没问题,不代表其他堆也没有问题,这样想思路就比较顺畅了,我们可以看看其他的堆,比如这里的 CLR私有堆,使用 !eeheap -loader 观察。


0:000> !eeheap -loader
Loader Heap:
--------------------------------------
...
Module 00007ff846e034c0: Size: 0x0 (0) bytes.
Module 00007ff846e03930: Size: 0x0 (0) bytes.
Module 00007ff846e04180: Size: 0x0 (0) bytes.
Module 00007ff846e047e0: Size: 0x0 (0) bytes.
Module 00007ff846e04e40: Size: 0x0 (0) bytes.
Total size:      Size: 0x0 (0) bytes.
--------------------------------------
Total LoaderHeap size:   Size: 0x47252000 (1193615360) bytes total, 0x1f68000 (32931840) bytes wasted.
=======================================

从卦中可以看到有非常多的 module 迸射出来,估计有几万个,并且可以看到总的大小是 1.19G,到这里基本就搞清楚了,然来是 程序集泄露

这里稍微补充一下,像这种问题早期可以使用 dotnet-counter 或者 Windows 的程序集指标 监控一下,或许你就能轻松找出原因,截图如下:


PS C:\Users\Administrator\Desktop> dotnet-counters monitor -n WebApplication2

而且 dotnet-counter 还是跨平台的,非常实用,大家可以琢磨琢磨,接下来抽一个module 用命令 !dumpmodule -mt 00007ff846e034c0 观察下,内部到底有哪些类型。


0:000> !dumpmodule -mt 00007ff846e034c0
Name: Unknown Module
Attributes:              Reflection IsDynamic IsInMemory 
Assembly:                000001c9e193b9e0
BaseAddress:             0000000000000000
...

Types defined in this module

              MT          TypeDef Name
------------------------------------------------------------------------------
00007ff846e03db0 0x02000002 

Types referenced in this module

              MT            TypeRef Name
------------------------------------------------------------------------------
00007ff820ff5748 0x02000002 xxx.xxx.Json.Converters.PolymorphismConverter`1
00007ff820e710f8 0x02000003 xxx.xxx.Models.IApiResult

0:000> !dumpmt -md 00007ff846e03db0
Number of IFaces in IFaceMap: 0
--------------------------------------
MethodDesc Table
           Entry       MethodDesc    JIT Name
00007FF822F05FA8 00007ff823285b50   NONE xxx.Json.Converters.PolymorphismConverter`1
00007FF822EFD5E8 00007ff82323b1b8   NONE System.Text.Json.Serialization.JsonConverter`1
00007FF822EFD5F0 00007ff82323b1c8   NONE System.Text.Json.Serialization.JsonConverter`1
00007FF8414CB978 00007ff846e03d88    JIT IApiResultDynamicJsonConverter..ctor()

仔细分析卦中信息,可以很明显的看到。

  • Json.Converters.PolymorphismConverter

看样子和牛顿有关系,并且还是一个自定义的 JsonConvert。

  • IApiResult 和 IApiResultDynamicJsonConverter

看样子是一个接口的返回协议类,需要在代码中重点关注。

有了这些信息,接下来就是重点关注代码中的 PolymorphismConverter 类,果然就找到了一处。

从类的定义来看,一般这种东西都是在 ConfigureServices 方法中做 初始化定义 的,按理说问题不大,那为什么会有问题呢?还得要查下它的引用,终于给找到了,截图如下:

这是一个低级错误哈,每次读取 ApiResult.Data 的时候都要 jsonSerializerOptions.AddPolymorphism(); 操作,也就每次都会创建程序集,终于真相大白。

三:总结

这种程序集泄露导致的生产事故不应该哈,反应了团队中多人协作的时候还是有待提高!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1074188.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

c++视觉处理---高斯滤波

高斯滤波处理 高斯滤波是一种常用的平滑滤波方法&#xff0c;它使用高斯函数的权重来平滑图像。高斯滤波通常用于去除噪声并保留图像中的细节。在OpenCV中&#xff0c;可以使用cv::GaussianBlur()函数来应用高斯滤波。 以下是cv::GaussianBlur()函数的基本用法&#xff1a; …

区块链技术的飞跃: 2023年的数字革命

随着时代的推进和技术的不断创新&#xff0c;2023年成为区块链技术飞跃发展的一年。区块链&#xff0c;一个曾经只是数字货币领域的技术&#xff0c;现在已经逐渐渗透到各个行业&#xff0c;成为推动数字经济发展的重要力量。在这个数字革命的时代&#xff0c;我们探讨区块链技…

纸黄金效率太低不如做现货

如果从字面上的意义去理解&#xff0c;纸黄金就是在账面上交易的黄金&#xff0c;具体来说它是国内银行为客户提供的一种记账式的黄金买卖&#xff0c;交易的记录和买卖的盈亏值&#xff0c;都只会在预先开设的账户上体现&#xff0c;投资过程中不涉及实物黄金的交收。 对于追求…

Docker基础(CentOS 7)

参考资料 hub.docker.com 查看docker官方仓库&#xff0c;需要梯子 Docker命令大全 黑马程序员docker实操教程 &#xff08;黑马讲的真的不错 容器与虚拟机 安装 yum install -y docker Docker服务命令 启动服务 systemctl start docker停止服务 systemctl stop docker重启…

LocalDateTime、LocalDate、Date、String相互转化大全及其注意事项

LocalDateTime、LocalDate、Date、String相互转化大全及其注意事项 一、前言 大家在开发过程中必不可少的和日期打交道&#xff0c;对接别的系统时&#xff0c;时间日期格式不一致&#xff0c;每次都要转化&#xff01; 二、LocalDateTime、LocalDate、Date三者联系 这里先…

二叉搜索树的基础操作

如果对于二叉搜索树不是太清楚&#xff0c;为什么要使用二叉搜索树&#xff1f;作者推荐&#xff1a;二叉搜索树的初步认识_加瓦不加班的博客-CSDN博客 定义节点 static class BSTNode {int key; // 若希望任意类型作为 key, 则后续可以将其设计为 Comparable 接口Object val…

查看本机Arp缓存,以及清除arp缓存

查看Arp缓存目录 Windows 系统使用 winR&#xff0c;输入cmd 在命令窗口输入 arp -a 删除Arp缓存目录 在命令窗口输入 arp -d * 查看主机路由表

js中 for、forEach、for...in、for...of循环的区别和使用

前端面试题库 &#xff08;面试必备&#xff09; 推荐&#xff1a;★★★★★ 地址&#xff1a;前端面试题库 js中 for、forEach、for...in、for...of循环的区别 我们全部以以下数组举例 var arr [1,2,3,4,5];for循环 for(语句 1; 语句 2; 语句 3){} &#xf…

ThreeJS-3D教学八-OBJLoader模型加载+动画

先看效果图&#xff1a; 本篇给大家介绍下模型加载的知识&#xff0c;用到了OBJLoader对应的模型&#xff0c;为了增加趣味性&#xff0c;花了些时间&#xff0c;利用new THREE.Points获取到模型上的点&#xff0c;做了一个动画效果&#xff0c;其实就是操作 Y轴上的点&#x…

[已解决]java-sun.security.validator.ValidatorException: PKIX path building failed

找了好多文章,终于找到个解决办法! 报错详情内容 解决办法 第一种&#xff08;适用于本人解决办法&#xff09;&#xff1a; httpclient-4.5.jar 定时发送http包&#xff0c;忽然有一天报错&#xff0c;http证书变更引起的。 之前的代码 try {CloseableHttpClient httpCli…

多测师肖sir_高级金牌讲师_python之基本使用003

python之基本使用 一、基础使用 1、python中的打印方式 格式&#xff1a;print&#xff08;打印内容&#xff09; 案例&#xff1a;print&#xff08;12&#xff09; 注意点&#xff1a; 打印的对象中&#xff1a;数值可以直接引用&#xff0c;字母或中文要加上引号&#xff08…

Eclipse导入项目之后中文注释乱码

1 问题 Eclipse导入项目之后中文注释乱码。原因&#xff1a;中文乱码的原因是因为编码的关系 2 解决方法 记事本打开查看编码方式 修改eclipse编码方式 在Eclipse中更改文件的编码方式可以通过以下步骤进行&#xff1a; 打开Eclipse&#xff0c;并导航到要更改编码方式的…

量化交易全流程(七)

本节目录 资金分配 实盘交易 vn.py框架 我将重点介绍资金分配的基础模型和实现。当然&#xff0c;这里介绍的模型是最基础的模型&#xff0c;现实实践中往往并不能直接使用。因为后续我将加入机器学习和深度学习在量化交易领域中的应用。 现代 / 均值——方差资产组合理论…

高级工技能等级认定理论部分 看了就过关

4 理论一_职业道德 4.1职业道德基本知识 4.1.1练习 4.2职业守则 4.2.1练习1 4.2.1练习2 5 理论二 _基础知识 5.1 法律责任 5.1.1 练习1 5.1.2 练习2 5.1.3 练习3 5.2 基础知识 5.2.1 练习1 5.2.2 练习2 5.2.3 练习3 5.2.4 练习4 6 理论三_网络与信息安全防护 6.1 网络相…

部署企业级ChatGPT,将AI整合进工作

引言 3月份AI应用大爆发催生了国内大量需求。 然而&#xff0c;所有的需求都不可避免得遇到很多非技术性的问题&#xff1a; 部署开源模型的成本巨大&#xff0c;且效果成谜&#xff0c;65B的模型推理应用最少需要130G显存&#xff0c;而微调训练则需要额外添加8倍的资源。 …

基于YOLO的BIM对象检测

我在此过程中使用的 BIM 数据集取自澳大利亚卫生设施指南。 该数据集包含一组房间数据表和房间布局表&#xff0c;旨在提供典型房间类型的合规示例&#xff0c;并减少规划和设计这些房间时“重新发明轮子”的需要。 推荐&#xff1a;用 NSDT编辑器 快速搭建可编程3D场景 1、合…

23.5 Bootstrap 框架6

1. 表单布局 部分表单类名介绍: * 1. form-label: 表单标签样式类, 用于定义表单的标签样式. * 2. form-control: 表单控件样式类, 用于定义输入框, 文本域等表单元素的样式.表单元素<input>, <textarea>, <select>在使用.form-control类的情况下, 宽度都是…

取消激光雷达/不升级Orin,小鹏P5改款背后的行业「痛点」

9月25日&#xff0c;小鹏汽车正式发布了旗下改款车型—2024款小鹏P5&#xff08;15.69-17.49万元&#xff09;。车型精简、降本增效&#xff08;减配&#xff09;成为新亮点。 在配置变化方面&#xff0c;智驾成为牺牲品。其中&#xff0c;高配Pro车型继续保留英伟达Xavier&…

Cpolar内网穿透工具在windows和Linux上具体使用

Cpolar内网穿透工具在windows和Linux上具体使用 一、Linux上部署的项目通过内网穿透实现外网访问项目二、Windows上部署的项目通过内网穿透实现外网访问项目 一、Linux上部署的项目通过内网穿透实现外网访问项目 一个免费的内网穿透方式&#xff0c;简单方便。 网址&#xff1a…

MyBatisPlus(十六)逻辑删除

说明 实际生产中的数据&#xff0c;一般不采用物理删除&#xff0c;而采用逻辑删除&#xff0c;也就是将一条记录的状态改为已删除。 逻辑删除&#xff0c;本质上是更新操作。 MyBatis Plus 框架&#xff0c;提供了逻辑删除功能。在配置了逻辑删除后&#xff0c;增删改查和统…