文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

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

2024-11-30 06:56

关注

话不多说,这篇看一个.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%
                             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()

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

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

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

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

图片

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

图片

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

三:总结

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

来源:一线码农聊技术内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯