利用Windbg分析Magicodes.IE一次错误编写导致内存剧增

由于这近一年时间一直忙于写书和工作,一直没有水文,但是近期有几位朋友使用我们的Magicodes.IE反馈在导出过程中内存暴涨...好吧,不管怎样,不能苦了我们朋友,接下来我们通过windbg来看一下什么原因导致的。

接下来我们先通过address -summary来看一下当前应用内存占用量。

0:000> !address -summary --- Usage Summary ---------------- RgnCount ----------- Total Size -------- %ofBusy %ofTotal Free 581 7df8`ef0c9000 ( 125.972 TB) 98.42% <unknown> 1678 206`ffb9e000 ( 2.027 TB) 99.99% 1.58% Image 950 0`064fd000 ( 100.988 MB) 0.00% 0.00% Heap 58 0`050f6000 ( 80.961 MB) 0.00% 0.00% Stack 156 0`04380000 ( 67.500 MB) 0.00% 0.00% Other 11 0`019ad000 ( 25.676 MB) 0.00% 0.00% TEB 52 0`00068000 ( 416.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 282 200`038a6000 ( 2.000 TB) 98.64% 1.56% MEM_PRIVATE 1674 7`07184000 ( 28.111 GB) 1.35% 0.02% MEM_IMAGE 950 0`064fd000 ( 100.988 MB) 0.00% 0.00% --- State Summary ---------------- RgnCount ----------- Total Size -------- %ofBusy %ofTotal MEM_FREE 581 7df8`ef0c9000 ( 125.972 TB) 98.42% MEM_RESERVE 295 205`f8659000 ( 2.023 TB) 99.79% 1.58% MEM_COMMIT 2611 1`188ce000 ( 4.384 GB) 0.21% 0.00% --- Protect Summary (for commit) - RgnCount ----------- Total Size -------- %ofBusy %ofTotal PAGE_READWRITE 1595 1`0dc6c000 ( 4.215 GB) 0.20% 0.00% PAGE_EXECUTE_READ 156 0`04d66000 ( 77.398 MB) 0.00% 0.00% PAGE_READONLY 600 0`03851000 ( 56.316 MB) 0.00% 0.00% PAGE_NOACCESS 99 0`021f2000 ( 33.945 MB) 0.00% 0.00% PAGE_EXECUTE_READWRITE 19 0`0027b000 ( 2.480 MB) 0.00% 0.00% PAGE_WRITECOPY 90 0`001a0000 ( 1.625 MB) 0.00% 0.00% PAGE_READWRITE | PAGE_GUARD 52 0`0009e000 ( 632.000 kB) 0.00% 0.00% --- Largest Region by Usage ----------- Base Address -------- Region Size ---------- Free 189`0413c000 7c6b`01ed4000 ( 124.418 TB) <unknown> 7dfb`2a153000 1f9`bd2ef000 ( 1.976 TB) Image 7ffc`883c1000 0`009ba000 ( 9.727 MB) Heap 183`0e9a1000 0`00f01000 ( 15.004 MB) Stack 37`62980000 0`0017b000 ( 1.480 MB) Other 183`77707000 0`01775000 ( 23.457 MB) TEB 37`62600000 0`00002000 ( 8.000 kB) PEB 37`627dd000 0`00001000 ( 4.000 kB)

MEM_COMMIT占用了4.384G,接下来我们利用eeheap -gc来检查托管堆。

0:000> !eeheap -gc GC Allocated Heap Size: Size: 0x11ac2568 (296494440) bytes. GC Committed Heap Size: Size: 0x120e7000 (302936064) bytes.

根据这些内存来看,似乎问题不是这里,大量的内存还是出现在非托管。我们利用Windows NT堆来看一下,其实在Windows中大多数的用户堆分配器都在ntdll.dll中的NT堆管理器API(RtlAllocateHeap/RtlFreeHeap)上建立,比如说C中的malloc/free和new/delete,另外还有COM框架中的SysAllocString以及在Win32中的LocalAlloc、GlobalAlloc和HeapAlloc,虽然说这些分配器都会创建不同的堆来存储它们的内存,但是他们最终都要调用ntdll.dll中的NT堆来实现。

0:000> !heap -s ************************************************************************************************************************ NT HEAP STATS BELOW ************************************************************************************************************************ NtGlobalFlag enables following debugging aids for new heaps: stack back traces LFH Key : 0x7cfd4cc2db4ddb4d Termination on corruption : ENABLED Heap Flags Reserv Commit Virt Free List UCR Virt Lock Fast (k) (k) (k) (k) length blocks cont. heap ------------------------------------------------------------------------------------- 0000018378fd0000 08000002 65128 15296 64928 1720 177 17 2 c LFH External fragmentation 11 % (177 free blocks) 00000183775c0000 08008000 64 4 64 2 1 1 0 0 000001837aa90000 08001002 1280 108 1080 26 3 2 0 0 LFH 000001837ad20000 08001002 60 8 60 2 1 1 0 0 000001837aca0000 08041002 60 8 60 5 1 1 0 0 000001887bfd0000 08001002 60 20 60 1 2 1 0 0 000001830cf30000 08001002 3324 1364 3124 19 10 3 0 0 LFH 000001830ce30000 08001002 60 8 60 5 1 1 0 0 -------------------------------------------------------------------------------------

输出结果如上所示,NT堆内容好少....什么原因....好吧根据 maoni所说,似乎是验证出了问题。

image

image

GC没有管辖这些内存,所以说还是我们编写的代码有问题,我们返过来再考虑一个事情,“导出进行时,内存会大量增加,导出完成后内存会降低下去”。我们来看一下代码,如下所示,其实我们现在明白的是,在我们执行期间肯定是这些内存一直“持有”,并没有被释放掉。

app.MapGet("/excel", async content => { string path = Path.Combine(Directory.GetCurrentDirectory(), "test.xlsx"); List<TestDto> list = new(); for (int i = 0; i < 400; i++) { list.Add(new TestDto { ImageUrl = "https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fup.enterdesk.com%2Fedpic_source%2F53%2F0a%2Fda%2F530adad966630fce548cd408237ff200.jpg&refer=http%3A%2F%2Fup.enterdesk.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1641193100&t=417a589da8c9ba3103ed74c33fbd6c70" }); } Stopwatch stopwatch = Stopwatch.StartNew(); ExcelExporter exporter = new ExcelExporter(); await exporter.Export(path, list); stopwatch.Stop(); await content.Response.WriteAsync(stopwatch.Elapsed.TotalSeconds.ToString()); });

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zzwzjp.html