国产精品电影_久久视频免费_欧美日韩国产激情_成年人视频免费在线播放_日本久久亚洲电影_久久都是精品_66av99_九色精品美女在线_蜜臀a∨国产成人精品_冲田杏梨av在线_欧美精品在线一区二区三区_麻豆mv在线看

記一次 .NET 某醫院預約平臺 內存泄露分析

開發 架構
在我分析的真實dump案例中,見過 Castle ProxyGenerator? 的泄露,也見過 CodeAnalysis.CSharp.Scripting? 的泄露,還真沒見過 XmlSerializer 的泄露,算是完美的補充了我的案例庫!

一:背景

1. 講故事

前幾天有位朋友找到我,說他的程序有內存泄露,讓我幫忙排查一下,截圖如下:

圖片圖片

說實話看到 32bit, 1.5G 這些關鍵詞之后,職業敏感告訴我,他這個可能是虛擬地址緊張所致,不管怎么說,有了 Dump 就可以上馬分析。

二:WinDbg分析

1. 虛擬地址緊張所致嗎

要看是不是虛擬地址緊張,可以用 !address -summary 觀察下內存段統計信息,截圖如下:

圖片圖片

我去,用 WinDbg Preview 盡然分析不了,在加載 ntdll 的過程中死掉了,如果你是我們調試訓練營的朋友,應該會深深的有體會,我們分析的第一個dump就存在這個情況,這個加載不了其實就預示著一種非托管泄露,這里暫不劇透。

用 WinDbg Preview 分析不了怎么辦呢?可以用 Windbg 的其他版本哈,比如 Windbg10, WinDbg6 等等,這里就采用 WinDbg10 X86 版本打開吧。

0:000> !address -summary

--- Usage Summary ---------------- RgnCount ----------- Total Size -------- %ofBusy %ofTotal
Free                                    179          8cbb1000 (   2.199 GB)           54.97%
Heap                                   6598          376f6000 ( 886.961 MB)  48.09%   21.65%
<unknown>                              3091          31954000 ( 793.328 MB)  43.02%   19.37%
Image                                   376           8c0d000 ( 140.051 MB)   7.59%    3.42%
Stack                                    75           1780000 (  23.500 MB)   1.27%    0.57%
Other                                     7             4e000 ( 312.000 kB)   0.02%    0.01%
TEB                                      25             19000 ( 100.000 kB)   0.01%    0.00%
PEB                                       1              1000 (   4.000 kB)   0.00%    0.00%

--- State Summary ---------------- RgnCount ----------- Total Size -------- %ofBusy %ofTotal
MEM_FREE                                179          8cbb1000 (   2.199 GB)           54.97%
MEM_COMMIT                             9821          6bfad000 (   1.687 GB)  93.68%   42.18%
MEM_RESERVE                             352           7492000 ( 116.570 MB)   6.32%    2.85%

從卦中 MEM_COMMIT 的 %ofTotal= 42.18% 來看,提交內存占總的虛擬地址比重還不到一半,這說明我的猜測是錯的,不存在虛擬地址緊張的情況,這里稍微提醒一下的是,這里不存在虛擬地址緊張是因為它開的是 Any CPU 模式,默認能吃到 4G 內存。

不管怎么說,現在被當頭一棒,既然這條路走不通,那會是什么情況導致的呢?一般來說這個內存量我是不愿意分析的,但既然分析到這里也只能繼續分析,接下來用 !eeheap -gc 觀察下托管堆內存占用情況。

0:000> !eeheap -gc
Number of GC Heaps: 1
generation 0 starts at 0x777c0434
generation 1 starts at 0x77781000
generation 2 starts at 0x01861000
ephemeral segment allocation context: none
 segment     begin  allocated      size
01860000  01861000  0285ffdc  0xffefdc(16773084)
...
77780000  77781000  77aa25c0  0x3215c0(3282368)
Large object heap starts at 0x02861000
 segment     begin  allocated      size
02860000  02861000  031e5cc0  0x984cc0(9981120)
Total Size:              Size: 0x1f7e47e4 (528369636) bytes.
------------------------------
GC Heap Size:    Size: 0x1f7e47e4 (528369636) bytes.

從卦中看當前托管堆也才 528M 和 提交內存 1.6G 相距甚遠,所以這個 dump 大概率是存在非托管內存泄露,其實 !address -summary 中的 Heap 也能佐證,說到底就是 ntheap 泄露。

2. ntheap 怎么啦

深挖 ntheap 我就不挖了,省的誤入歧途,文章開頭我說過 ntdll 無法加載的現象預示著一種非托管泄露,對 ,就是 GC 的加載堆泄露,加載堆是 CLR 用來映射 C# 程序集,模塊,類型,方法等用途的一塊私有內存,那怎么去洞察它呢?可以使用 !eeheap -loader 命令洞察。

0:000> !eeheap -loader
Loader Heap:
--------------------------------------
...
Module 05829f78: Size: 0x0 (0) bytes.
Module 0582a8f8: Size: 0x0 (0) bytes.
Module 0582b278: Size: 0x0 (0) bytes.
Module 0582bbf8: Size: 0x0 (0) bytes.
Module 0582c578: Size: 0x0 (0) bytes.
Module 0582cef8: Size: 0x0 (0) bytes.
Module 0582d878: Size: 0x0 (0) bytes.
...
Module 362ea420: Size: 0x0 (0) bytes.
Total size:      Size: 0x0 (0) bytes.
--------------------------------------
Total LoaderHeap size:   Size: 0x7e7e000 (132636672) bytes total, 0x28000 (163840) bytes wasted.
=======================================

雖然加載堆只統計到了 132M,但其中的 module 高達 2.3w 個,其實這里會有一些相關內存是加載堆之外無法統計到的,一般正常的程序不可能有這么多的module,所以這就是我們接下來突破的點,那怎么突破呢?最好的辦法就是觀察下這個 module 中到底有什么 type,使用 !dumpmodule 命令即可。

0:000> !dumpmodule -mt 0582d878
Name:       Unknown Module
Attributes: Reflection 
Assembly:   0c229d38
LoaderHeap:              00000000
TypeDefToMethodTableMap: 050676e4
TypeRefToMethodTableMap: 050676f8
MethodDefToDescMap:      0506770c
FieldDefToDescMap:       05067734
MemberRefToDescMap:      00000000
FileReferencesMap:       05067784
AssemblyReferencesMap:   05067798

Types defined in this module

      MT  TypeDef Name
------------------------------------------------------------------------------
0582dcb0 0x02000002 
0582df90 0x02000003 
0582e018 0x02000004 
0582e0b8 0x02000005 
0582e194 0x02000006 

Types referenced in this module

      MT    TypeRef Name
------------------------------------------------------------------------------

從模塊中并沒有看到類型的文字描述,那怎么辦呢,我們隨便抽一個 mt 看下這個 mt 下有什么方法,使用 !dumpmt 命令即可。

0:000> !dumpmt -md 0582dcb0
EEClass:         05068980
Module:          0582d878
Name:            
mdToken:         02000002
File:            Unknown Module
BaseSize:        0x44
ComponentSize:   0x0
Slots in VTable: 8
Number of IFaces in IFaceMap: 0
--------------------------------------
MethodDesc Table
   Entry MethodDe    JIT Name
739819c8 735e61fc PreJIT System.Object.ToString()
73987850 735e6204 PreJIT System.Object.Equals(System.Object)
7398bd80 735e6224 PreJIT System.Object.GetHashCode()
738ddbe8 735e6238 PreJIT System.Object.Finalize()
0583b529 0582dc8c   NONE Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationWriterCallBack.InitCallbacks()
0583b52d 0582dc94   NONE Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationWriterCallBack..ctor()
0583c7d0 0582dc74    JIT Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationWriterCallBack.Write3_root(System.Object)
0583c868 0582dc80    JIT Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationWriterCallBack.Write2_CallBack(System.String, System.String, xxx.Models.xxxBack, Boolean, Boolean)

看到卦中的這些信息,我相信有很多朋友知道是怎么回事了,對,就是 Serialization 泄露,那它序列化什么類型呢 ? 從卦中看就是 xxx.Models.xxxBack 類,即 xmlSerializer.Serialize(xxx.Models.xxxBack) 的相關邏輯,接下來就需要逆向看下到底是哪里寫的,結果發現是他的底層庫封裝的,有些方法有問題,有些沒問題,真的是無語哈。

//有問題的方法
    public static string Serialize(object o, Encoding encoding, string rootName)
    {
        XmlSerializer xmlSerializer = new XmlSerializer(o.GetType(), new XmlRootAttribute(rootName));
        ...
        xmlSerializer.Serialize(memoryStream, o, xmlSerializerNamespaces);
        return encoding.GetString(memoryStream.ToArray());
    }

    //正確的方法
    public static string Serialize(object Obj, Encoding encoding)
    {
        ...
        using (XmlWriter xmlWriter = XmlWriter.Create(memoryStream, xmlWriterSettings))
        {
            XmlSerializerNamespaces xmlSerializerNamespaces = new XmlSerializerNamespaces();
            xmlSerializerNamespaces.Add("", "");
            new XmlSerializer(Obj.GetType()).Serialize(xmlWriter, Obj, xmlSerializerNamespaces);
        }
        return encoding.GetString(memoryStream.ToArray());
    }

這是一個老生常談的問題,如果你用 new XmlSerializer(o.GetType(), new XmlRootAttribute(rootName)); 模式的話,一定要緩存起來,否則就會泄露,只能說是微軟造的一個大坑吧,多少人都踩上去了。

三:總結

在我分析的真實dump案例中,見過 Castle ProxyGenerator 的泄露,也見過 CodeAnalysis.CSharp.Scripting 的泄露,還真沒見過 XmlSerializer 的泄露,算是完美的補充了我的案例庫!

責任編輯:武曉燕 來源: 一線碼農聊技術
相關推薦

2023-05-15 11:15:50

.NET門診語句

2023-10-07 13:28:53

.NET軟件賬本

2023-06-26 00:12:46

2021-11-02 07:54:41

內存.NET 系統

2023-09-26 01:11:58

MES非托管泄露

2022-10-24 07:48:37

.NETCPUGC

2024-03-28 12:56:36

2023-04-06 10:52:18

2024-12-27 13:31:18

.NETdump調試

2021-10-09 10:24:08

NET爬蟲內存

2024-07-01 13:00:24

.NET網絡邊緣計算

2024-11-29 10:06:59

2022-01-17 21:28:36

管理系統.NET

2024-07-09 11:51:20

Windows線程池源碼

2023-06-29 17:55:00

.NET日志WinDbg

2025-10-29 01:11:00

.NET系統windows

2024-09-14 10:28:56

.NET卡死程序

2021-10-27 07:30:32

.NETCPU論壇

2022-10-25 14:17:01

.NET代碼程序

2024-05-31 12:56:06

.NET代碼方法
點贊
收藏

51CTO技術棧公眾號

欧美日韩国产123| 欧美日韩黄色影视| 国产91精品久久久久| 欧美在线一卡| 国产一区欧美二区| 成人国产精品色哟哟| 欧美aaa大片视频一二区| 欧美性开放视频| 99热这里只有精品在线播放| 久久久久欧美精品| 91九色精品视频| 豆花视频一区| 日韩二区三区在线| 1024国产在线| 精品久久久久久久中文字幕| 可以免费观看av毛片| 国产精品影视在线| 欧美日韩亚洲在线| 狠狠噜噜久久| 国产精品扒开腿做爽爽爽视频| 久久久加勒比| 日韩成人av一区| 在线视频中文字幕第一页| 欧美日韩综合视频| 在线视频您懂的| 日本男人操女人| 伊人久久大香线蕉综合影院首页| 欧美哺乳videos| 九义人在线观看完整免费版电视剧| 亚洲免费在线看| 91看片在线免费观看| 成人一道本在线| 超薄肉色丝袜足j调教99| 日韩av中文字幕一区二区三区| 国产欧美日韩一区| 激情欧美一区| 欧美xxxx黑人又粗又长密月| 亚洲激情综合| 鲁丝一区鲁丝二区鲁丝三区| 99精品视频免费观看| 国产另类自拍| 日韩午夜在线| 久久国产精品免费一区| 香蕉视频成人在线观看| 久久久久久欧美精品色一二三四| 一区二区黄色| 日本视频一区在线观看| 免费看欧美女人艹b| 国产对白在线播放| 成人高清av在线| 精品久久久久久中文字幕2017| 久久久蜜桃精品| 国产三级三级看三级| 亚洲精品五月天| 日本人妖在线| 欧美剧情电影在线观看完整版免费励志电影| 黄色大片在线免费观看| 欧美精品亚洲二区| 国产精品迅雷| 免费av一区二区| 精品美女视频| 国产69精品久久久久9999apgf| 国产精品入口| 97精品国产97久久久久久粉红| 成人短视频下载| 黄页免费观看| 欧美艳星brazzers| 色戒汤唯在线观看| 亚洲欧美日韩爽爽影院| 国模大尺度视频一区二区| 欧美做受高潮1| 欧美88av| 久久精品国产精品亚洲精品色| 国产特级淫片高清视频| 国产精品亚洲一区二区三区妖精| 日韩精品一区在线视频| 国产精品国产三级国产普通话99| 在线中文视频| 日韩精品福利网站| 激情av综合| 国产视频99| 东方aⅴ免费观看久久av| 国产又大又黄又猛| 欧美亚日韩国产aⅴ精品中极品| 超碰在线97国产| 九九九热精品免费视频观看网站| 欧美艳星介绍134位艳星| 亚洲人成网站在线观看播放| 久久久久国产成人精品亚洲午夜 | 久久久不卡网国产精品二区| 中文字幕校园春色| 亚洲精品在线观看网站| 红杏aⅴ成人免费视频| 国产经品一区二区| 26uuuu精品一区二区| 香蕉视频在线观看免费| 日韩一区二区影院| 欧美亚洲色图校园春色| 欧美理论一区二区| 国产精品日韩成人| 黑人另类精品××××性爽| 777精品视频| 国产自产高清不卡| 你懂的在线播放| 久久久精品美女| 久久久久久久欧美精品| 2018av男人天堂| 国产亚洲欧洲高清| 亚洲高清电影| 国产偷激情在线| 亚洲天堂av综合网| 欧美精品一卡| av网站免费观看| 色爱精品视频一区| 免费在线亚洲| 天堂91在线| 7777kkkk成人观看| 国产成人精品三级| 性国产高清在线观看| 国产精品久久久久久久久免费| 成人的网站免费观看| 怡红院在线播放| www日韩av| 午夜精品久久久久影视| 高潮久久久久久久久久久久久久| 欧美另类videosbestsex日本| 欧美日韩一区二区在线观看| 亚洲理论电影| 国产成人久久婷婷精品流白浆| 精品黑人一区二区三区久久| 91视频综合| h七七www色午夜日本| 久久伊人免费视频| 白白色 亚洲乱淫| 影视一区二区三区| 色中文字幕在线观看| 日韩女优电影在线观看| 亚洲国产午夜| 91.com视频| 老汉av免费一区二区三区| 欧美亚洲日本在线观看| 精品处破学生在线二十三| 午夜视频在线免费| 欧美成人一二三| 国产成人亚洲精品青草天美| 日本亚洲精品| 亚洲www在线| 欧美日韩免费一区| 欧美肥老太太性生活| 免费av一级电影| 97在线观看视频国产| 久久免费午夜影院| www.91精品| 无码aⅴ精品一区二区三区浪潮| 亚洲人av在线影院| 成人污视频在线观看| 国产激情久久| 激情婷婷综合网| 18一19gay欧美视频网站| 美女黄色片网站| 免费看污污视频| 亚洲欧美日韩在线综合 | 91视频国产观看| 欧美三级黄网| 成人免费看片视频| 日韩欧美综合在线视频| 一区二区电影| 搞黄视频在线观看| 国产精品一区二区三区精品| 欧美系列亚洲系列| 亚洲人成网7777777国产| 免费在线成人网| 亚洲第一会所001| 国产va亚洲va在线va| 欧美成人午夜剧场免费观看| 国产日本欧洲亚洲| 视频一区欧美| 欧美日韩激情视频一区二区三区| 国产精品99久久久久久久| 欧美一区二区国产| 成人做爰69片免费看网站| 日韩区欧美区| 在线免费色视频| 蜜桃网站成人| 日韩中文字在线| 国产精品国产自产拍高清av| 欧美码中文字幕在线| 久久av免费观看| 久久人人爽爽人人爽人人片av| 国产美女精品免费电影| 久久久亚洲网站| 精品国产免费人成在线观看| 欧美一级免费观看| 午夜天堂影视香蕉久久| 国产激情视频一区二区三区欧美 | 中文字幕电影一区| 老牛精品亚洲成av人片| 日本女优北野望在线电影| 古典武侠综合av第一页| 亚洲高清久久网|