For more high-quality dry goods: See my GitHub:dotnetfly
A: background
1. Tell a story
To be honest, I was not prepared to interpret this dump in the last article, but it has two points that deeply moved me.
-
I’ve heard so many times that you can do game development with Unity, but seeing is believing.
-
There are a lot of jin Yong wuxia novel names in the game, it is very pleasing to the eye.
000000df315978a8 0 3Jade bone fan000000df31597cd8 0 3Yunlong gun000000df31596d88 0 3Evil wind claw000000df315967a8 0 4The snow chain of silk000000df31596ad0 0 4B wooden excalibur000000df31596040 0 3Star yao crown000000df31595328 0 3Sharply hammer...Copy the code
So with such a good dump, I have to leave something for it.
Anyway, this fate started last month when a friend said that its program virtual memory occupation is very large, and asked how to solve it, as shown below:
Dump: Dump: dump: dump: dump: dump: dump: dump: dump: dump: dump
Two: Windbg analysis
1. Where exactly is the leak
Analyze the memory problem and, again, split it in two to see which area (managed or unmanaged) is leaking.
First take a look at the total process memory, use! Address-summary command.
0:087> !address -summary
--- Usage Summary ---------------- RgnCount ----------- Total Size -------- %ofBusy %ofTotal
Free 458 7ffe`9e6a8000 ( 127.995 TB) 100.00%
Heap 48514 1`005fd000 ( 4.006 GB) 72.51% 0.00%
<unknown> 2504 0`2c6ad000 ( 710.676 MB) 12.56% 0.00%
Stack 504 0`2a000000 ( 672.000 MB) 11.88% 0.00%
Image 410 0`0a971000 ( 169.441 MB) 3.00% 0.00%
Other 18 0`001dc000 ( 1.859 MB) 0.03% 0.00%
TEB 168 0`00150000 ( 1.312 MB) 0.02% 0.00%
PEB 1 0`00001000 ( 4.000 kB) 0.00% 0.00% -- -- --Type Summary (for busy) ------ RgnCount ----------- Total Size -------- %ofBusy %ofTotal
MEM_PRIVATE 51581 1`5130f000 ( 5.269 GB) 95.36% 0.00% MEM_IMAGE 416 0 '0aa6b000 ( 170.418 MB) 3.01% 0.00% MEM_MAPPED 122 0 '05bce000 ( 91.805 MB) 1.62% 0.00% - State Summary -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- RgnCount -- -- -- -- -- -- -- -- -- -- - the Total Size -- -- -- -- -- -- -- -- % % ofBusy ofTotal MEM_FREE 458 7ffe`9e6a8000 ( 127.995 TB) 100.00% MEM_COMMIT 51465 1 '1c741000 ( 4.445 GB) 80.45% 0.00% MEM_RESERVE 654 0 '45207000 ( 1.080 GB) 19.55% 0.00%
Copy the code
MEM_COMMIT= 4.4g MEM_COMMIT= 4.4g Eeheap-gc command.
0:087> !eeheap -gc
Number of GC Heaps: 1
generation 0 starts at 0x000000df3118dc48
generation 1 starts at 0x000000df3118b098
generation 2 starts at 0x000000df30fc1000
ephemeral segment allocation context: none
segment begin allocated size
000000df30fc0000 000000df30fc1000 000000df3178cae0 0x7cbae0(8174304)
Large object heap starts at 0x000000df40fc1000
segment begin allocated size
000000df40fc0000 000000df40fc1000 000000df410637b8 0xa27b8(665528)
Total Size: Size: 0x86e298 (8839832) bytes.
------------------------------
GC Heap Size: Size: 0x86e298 (8839832) bytes.
Copy the code
GC Heap Size= 8839832 Byte = 8M 🤣🤣🤣🤣, obviously this is an unmanaged memory leak, since the direction is determined, then check the unmanaged area!
2. Explore unmanaged leaks
According to experience, to find unmanaged leakage, first look at the loader heap, many programs are often caused by the dynamic creation of too many assemblies, such as the classic Castle, XmlSerializer, interested friends can find this information online, here use! View the eeheap-loader command.
0:087> !eeheap -loader
--------------------------------------
Jit code heap:
LoaderCodeHeap: 0000000000000000(0:0) Size: 0x0 (0) bytes.
Total size: Size: 0x0 (0) bytes.
--------------------------------------
Module Thunk heaps:
Module 00007ffda5fa1000: Size: 0x0 (0) bytes.
Module 00007ffd485c4148: Size: 0x0 (0) bytes.
Module 00007ffda2631000: Size: 0x0 (0) bytes.
Module 00007ffda5331000: Size: 0x0 (0) bytes.
Module 00007ffdac621000: Size: 0x0 (0) bytes.
Module 00007ffdac4e1000: Size: 0x0 (0) bytes.
Module 00007ffda48b1000: Size: 0x0 (0) bytes.
Module 00007ffda1791000: Size: 0x0 (0) bytes.
Module 00007ffd487b1858: Size: 0x0 (0) bytes.
Total size: Size: 0x0 (0) bytes.
--------------------------------------
Module Lookup Table heaps:
Module 00007ffda5fa1000: Size: 0x0 (0) bytes.
Module 00007ffd485c4148: Size: 0x0 (0) bytes.
Module 00007ffda2631000: Size: 0x0 (0) bytes.
Module 00007ffda5331000: Size: 0x0 (0) bytes.
Module 00007ffdac621000: Size: 0x0 (0) bytes.
Module 00007ffdac4e1000: Size: 0x0 (0) bytes.
Module 00007ffda48b1000: Size: 0x0 (0) bytes.
Module 00007ffda1791000: Size: 0x0 (0) bytes.
Module 00007ffd487b1858: Size: 0x0 (0) bytes.
Total size: Size: 0x0 (0) bytes.
--------------------------------------
Total LoaderHeap size: Size: 0x99000 (626688) bytes total, 0x2000 (8192) bytes wasted.
=======================================
Copy the code
Total heap size= 626K Total heap size= 626K The heap -s command.
0:087>! heap -s * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * NT HEAP STATS BELOW * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * LFH Key :0xb6c37b3e3a4a189e
Termination on corruption : ENABLED
Heap Flags Reserv Commit Virt Free List UCR Virt Lock Fast
(k) (k) (k) (k) length blocks cont. heap ------------------------------------------------------------------------------------- 000000df2e680000 00000002 4145084 4130108 4144304 1537 775 260 1 4 LFH 000000df2e1f0000 00008000 64 4 64 2 1 1 0 0 000000df2e830000 00001002 1860 172 1080 15 5 2 0 0 LFH 000000df2ec80000 00001002 1860 236 1080 5 7 2 0 0 LFH 000000df309e0000 00001002 60 8 60 2 1 1 0 0 000000df30bb0000 00041002 60 8 60 5 1 1 0 0 000000df49bd0000 00001002 840 44 60 3 3 1 0 0 LFH 000000df49b20000 00041002 1860 96 1080 8 3 2 0 0 LFH 000000df30b40000 00001002 60 20 60 9 2 1 0 0 000000df30b30000 00001002 1860 152 1080 11 8 2 0 0 LFH 000000df4bbb0000 00001002 3904 1292 3124 49 6 3 0 0 LFH 000000df89920000 00001002 1860 372 1080 14 7 2 0 0 LFH 000000df89be0000 00001006 1860 280 1080 23 2 2 0 0 LFH 000000df56f40000 00001006 32372 26204 31592 1434 21 6 0 6b LFH 000000df56f10000 00001006 1860 176 1080 21 3 2 0 0 LFH 000000df89ac0000 00001006 3904 2160 3124 67 4 3 0 2e LFH -------------------------------------------------------------------------------------Copy the code
Heap = 000000DF2e680000; heap= 000000DF2e680000; heap= 000000DF2e680000; The heap-stat -h 000000df2e680000 command displays heap statistics.
0:087> !ext.heap -stat -h 000000df2e680000
heap @ 000000df2e680000
group-by: TOTSIZE max-display: 20
size #blocks total ( %) (percent of total busy bytes)
2000 4cfd2 - 99fa4000 (68.76)
58 9d7492 - 36201230 (24.17)
12c 267e8 - 2d1c3e0 (1.26)
21d1 c46 - 19f0b26 (0.72)
4020 634 - 18dc680 (0.69)
a0 26d00 - 1842000 (0.68)
a 1d3ebb - 124734e (0.51)
10 f8d99 - f8d990 (0.43)
6 16adae - 881214 (0.24)
b b3508 - 7b4758 (0.22)
7 115125 - 793803 (0.21)
5 17b833 - 7698ff (0.21)
c 86027 - 6481d4 (0.18)
9 afef9 - 62f6c1 (0.17)
d 6a80f - 5688c3 (0.15)
f 4f5a9 - 4a64e7 (0.13)
e 54814 - 49f118 (0.13)
8 8b092 - 458490 (0.12)
13 3139b - 3a7481 (0.10)
15 25d06 - 31a17e (0.09)
Copy the code
The heap was filled by size=2000 and size=58. The heap was filled by size=2000 and size=58. The heap was filled by size=2000 and size=58. Heap-flt s 2000 Finds the first address of all these blocks in the heap.
0:087> !ext.heap -flt s 2000
_HEAP @ df2e680000
HEAP_ENTRY Size Prev Flags UserPtr UserSize - state
000000df2e702dd0 0201 0000 [00] 000000df2e702de0 02000 - (busy)
000000df2e72c7e0 0201 0201 [00] 000000df2e72c7f0 02000 - (busy)
000000df517400c0 0201 0201 [00] 000000df517400d0 02000 - (busy)
000000df517420d0 0201 0201 [00] 000000df517420e0 02000 - (busy)
000000df517440e0 0201 0201 [00] 000000df517440f0 02000 - (busy)
000000df517460f0 0201 0201 [00] 000000df51746100 02000 - (busy)
000000df51748100 0201 0201 [00] 000000df51748110 02000 - (busy)
000000df5174a110 0201 0201 [00] 000000df5174a120 02000 - (busy)
000000df5174c120 0201 0201 [00] 000000df5174c130 02000 - (busy)
000000df5174e130 0201 0201 [00] 000000df5174e140 02000 - (busy)
000000df51750140 0201 0201 [00] 000000df51750150 02000 - (busy)
...
Copy the code
The above HEAP_ENTRY is the first address of the block. Since there are approximately 4cfd2= 31.5W such blocks, it is impossible to list them one by one. The next step is to use DC to observe the contents of the memory blocks of these blocks to find the rules. Still have to use the script, here again take the first 100 thousand view.
function show_all_blocksize() {
var output = exec(! "" ext.heap -flt s 58").Take(10000);
for (var line of output) {
var heap_entry_address = line.trim().split(' ') [0];
if (heap_entry_address.indexOf("00") = =- 1) continue; show_heap_entry(heap_entry_address); }}function show_heap_entry(heap_entry_address) {
var pageIndex = (index++);
var path = ".writemem D:\\file\\"+ pageIndex + ".txt " + heap_entry_address + " L? 0x58";
var output = exec(path);
log("pageIndex=" + pageIndex);
}
Copy the code
After executing the script generation to TXT, the screenshot is as follows:
Observing that there is a lot of user information in the heap, and then using that information to identify friends.
After a brief conversation with a friend, that’s all I can do. Case closed.
Three:
The cause of this accident is due to C# call Lua, Lua did not make a reasonable memory release caused by unmanaged leakage, specific how to release in the code layer, this is up to my friend luck.
Finally, a small egg, friends are too polite.
Never seen such a big red envelope, I unexpectedly received 🤣🤣🤣, backhanded to the company’s r & D partners a cup of afternoon tea, here to say thank you to our friends, 😘 college