当前位置:首页 > 科技  > 软件

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

来源: 责编: 时间:2023-10-08 07:05:13 167观看
导读一:背景1. 讲故事中秋国庆长假结束,哈哈,在老家拍了很多的短视频,有兴趣的可以上B站观看:https://space.bilibili.com/409524162 ,今天继续给大家分享各种奇奇怪怪的.NET生产事故,希望能帮助大家在未来的编程之路上少踩坑。

一:背景

1. 讲故事

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

话不多说,这篇看一个.NET程序集泄露导致的CLR私有堆泄露的案例,这个泄露和 JsonConvert 有关,哈哈,相信你肯定比较惊讶!xve28资讯网——每日最新资讯28at.com

二:WinDbg 分析

1. 到底是哪里的泄露

首先观察一下进程的提交内存的大小,即通过 !address -summary 观察。xve28资讯网——每日最新资讯28at.com

0:000> !address -summary--- Usage Summary ---------------- RgnCount ----------- Total Size -------- %ofBusy %ofTotalFree                                    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 %ofTotalMEM_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 %ofTotalMEM_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 ,差不多占了一半,但不能说明就是非托管内存泄露,接下来继续观察下托管堆。xve28资讯网——每日最新资讯28at.com

0:000> !eeheap -gcNumber of GC Heaps: 8------------------------------Heap 7 (000001C4971013A0)generation 0 starts at 0x000001C817D201A0generation 1 starts at 0x000001C817C878D8generation 2 starts at 0x000001C817261000ephemeral segment allocation context: none         segment             begin         allocated              size000001C817260000  000001C817261000  000001C819013F98  0x1db2f98(31141784)Large object heap starts at 0x000001C907261000         segment             begin         allocated              size000001C907260000  000001C907261000  000001C907261018  0x18(24)Pinned object heap starts at 0x000001C987261000000001C987260000  000001C987261000  000001C9872ABA50  0x4aa50(305744)Heap Size:       Size: 0x1dfda00 (31447552) bytes.------------------------------GC Heap Size:    Size: 0xba26488 (195191944) bytes.

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

2. 到底是哪里的泄露

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

0:000> !eeheap -loaderLoader 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,到这里基本就搞清楚了,然来是 程序集泄露。xve28资讯网——每日最新资讯28at.com

这里稍微补充一下,像这种问题早期可以使用 dotnet-counter 或者 Windows 的程序集指标 监控一下,或许你就能轻松找出原因,截图如下:xve28资讯网——每日最新资讯28at.com

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

图片图片xve28资讯网——每日最新资讯28at.com

而且 dotnet-counter 还是跨平台的,非常实用,大家可以琢磨琢磨,接下来抽一个module 用命令 !dumpmodule -mt 00007ff846e034c0 观察下,内部到底有哪些类型。xve28资讯网——每日最新资讯28at.com

0:000> !dumpmodule -mt 00007ff846e034c0Name: Unknown ModuleAttributes:              Reflection IsDynamic IsInMemory Assembly:                000001c9e193b9e0BaseAddress:             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`100007ff820e710f8 0x02000003 xxx.xxx.Models.IApiResult0:000> !dumpmt -md 00007ff846e03db0Number of IFaces in IFaceMap: 0--------------------------------------MethodDesc Table           Entry       MethodDesc    JIT Name00007FF822F05FA8 00007ff823285b50   NONE xxx.Json.Converters.PolymorphismConverter`100007FF822EFD5E8 00007ff82323b1b8   NONE System.Text.Json.Serialization.JsonConverter`100007FF822EFD5F0 00007ff82323b1c8   NONE System.Text.Json.Serialization.JsonConverter`100007FF8414CB978 00007ff846e03d88    JIT IApiResultDynamicJsonConverter..ctor()

仔细分析卦中信息,可以很明显的看到。xve28资讯网——每日最新资讯28at.com

  • Json.Converters.PolymorphismConverter

看样子和牛顿有关系,并且还是一个自定义的 JsonConvert。xve28资讯网——每日最新资讯28at.com

  • IApiResult 和 IApiResultDynamicJsonConverter

看样子是一个接口的返回协议类,需要在代码中重点关注。xve28资讯网——每日最新资讯28at.com

有了这些信息,接下来就是重点关注代码中的 PolymorphismConverter 类,果然就找到了一处。xve28资讯网——每日最新资讯28at.com

图片图片xve28资讯网——每日最新资讯28at.com

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

图片图片xve28资讯网——每日最新资讯28at.com

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

三:总结

这种程序集泄露导致的生产事故不应该哈,反应了团队中多人协作的时候还是有待提高!xve28资讯网——每日最新资讯28at.com

本文链接:http://www.28at.com/showinfo-26-12298-0.html记一次 .NET某账本软件 非托管泄露分析

声明:本网页内容旨在传播知识,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。邮件:2376512515@qq.com

上一篇: 12字真言,教你如何选择Gradle和Maven

下一篇: Sentinel安装和项目整合Sentinel

标签:
  • 热门焦点
Top