一:背景 1. 講故事 前幾天有位朋友找到我,說他的程式會偶發性的報 存儲空間不足,無法處理此命令 的錯誤,讓我幫忙看下到底怎麼回事,哈哈,人家是有備而來,dump都準備好了,話不多說,直接分析開乾。 二:WinDbg 分析 1. 捕獲dump中的異常 一般來講別人說的只是一個參考,我們需要自己到d ...
一:背景
1. 講故事
前幾天有位朋友找到我,說他的程式會偶發性的報 存儲空間不足,無法處理此命令
的錯誤,讓我幫忙看下到底怎麼回事,哈哈,人家是有備而來,dump都準備好了,話不多說,直接分析開乾。
二:WinDbg 分析
1. 捕獲dump中的異常
一般來講別人說的只是一個參考,我們需要自己到dump中去驗證,可以用 !t
觀察下。
0:000:x86> !t
ThreadCount: 61
UnstartedThread: 0
BackgroundThread: 52
PendingThread: 0
DeadThread: 3
Hosted Runtime: no
Lock
ID OSID ThreadOBJ State GC Mode GC Alloc Context Domain Count Apt Exception
0 1 9310 004e24f8 26020 Preemptive 00000000:00000000 004d94e0 0 STA System.Runtime.InteropServices.COMException 42b57774 (nested exceptions)
...
0:000:x86> !PrintException /d 42b57774
Exception object: 42b57774
Exception type: System.Runtime.InteropServices.COMException
Message: 存儲空間不足,無法處理此命令。 (Exception from HRESULT: 0x80070008)
InnerException: <none>
StackTrace (generated):
SP IP Function
00000000 00000001 mscorlib_ni!System.Runtime.InteropServices.Marshal.ThrowExceptionForHRInternal(Int32, IntPtr)+0x2
003FAC0C 6F5655C9 mscorlib_ni!System.Runtime.InteropServices.Marshal.ThrowExceptionForHR(Int32, IntPtr)+0x9
003FAC10 55171671 PresentationCore_ni!MS.Internal.Text.TextInterface.Native.Util.ConvertHresultToException(Int32)+0x702961
003FAC24 54A56129 PresentationCore_ni!MS.Internal.Text.TextInterface.FontFace.GetDesignGlyphMetrics(UInt16*, UInt32, MS.Internal.Text.TextInterface.GlyphMetrics*)+0x79
003FAC60 54A73B77 PresentationCore_ni!System.Windows.Media.GlyphTypeface.GlyphMetrics(UInt16*, Int32, MS.Internal.Text.TextInterface.GlyphMetrics*, Double, System.Windows.Media.TextFormattingMode, Boolean)+0x47
...
從卦中信息看確實拋了一個 COMException
異常,並且真的有這麼一條錯誤信息 存儲空間不足,無法處理此命令
,而且從調用棧來看貌似是wpf在處理 字形信息,一般來說這種代碼是千錘百煉不會出任何問題的。
作為現代化的程式員,必須通過 百度搜索
尋找一下天涯淪落人,通過搜索得知大概有兩種情況:
- 硬碟存儲空間不足所致
- 記憶體不足所致
2. 是硬碟存儲空間不足嗎
要想驗證是不是這種情況導致的,只能詢問下朋友,據朋友反饋不存在這個問題,所以這條路就堵死了。
3. 是記憶體不足嗎
要想排查這種情況只能觀察進程的 MEM_COMMIT
指標,使用 !address -summary
。
0:000:x86> !address -summary
...
--- State Summary ---------------- RgnCount ----------- Total Size -------- %ofBusy %ofTotal
MEM_COMMIT 3773 6e617000 ( 1.725 GB) 89.86% 86.24%
MEM_RESERVE 702 c4c6000 ( 196.773 MB) 10.01% 9.61%
MEM_FREE 667 5513000 ( 85.074 MB) 4.15%
...
--- Largest Region by Usage ----------- Base Address -------- Region Size ----------
Heap32 23470000 fd0000 ( 15.812 MB)
<unknown> 474b0000 19c4000 ( 25.766 MB)
Image 2fbf1000 1180000 ( 17.500 MB)
Free 7355b000 1a5000 ( 1.645 MB)
Stack32 c50000 fd000 (1012.000 kB)
Stack64 5a0000 39000 ( 228.000 kB)
Other 8e0000 181000 ( 1.504 MB)
TEB64 7ee37000 2000 ( 8.000 kB)
Heap64 120000 65000 ( 404.000 kB)
TEB32 7ee39000 1000 ( 4.000 kB)
Other32 290000 1000 ( 4.000 kB)
PEB64 7efdf000 1000 ( 4.000 kB)
PEB32 7efde000 1000 ( 4.000 kB)
...
從卦中的信息看,當前程式提交記憶體是 1.7G
,看到這個值馬上就想到了 2G虛擬地址
,那這個程式是不是x86的呢?除了觀察記憶體地址,也可以通過觀察 PE 頭獲知。
0:000:x86> lm
start end module name
01380000 01450000 xxxWinApp C (no symbols)
0:000:x86> !dh xxxWinApp
File Type: EXECUTABLE IMAGE
FILE HEADER VALUES
14C machine (i386)
3 number of sections
654073AD time date stamp Tue Oct 31 11:25:33 2023
0 file pointer to symbol table
0 number of symbols
E0 size of optional header
102 characteristics
Executable
32 bit word machine
從卦中的 32 bit word machine
來看,確實沒有開大地址,看樣子是受到了 2G 的虛擬地址限制。
不過說實話我真的佩服寫這個軟體的程式員,在上限 2G 的空間內,能將程式控制在 1.72G
都不崩,把記憶體壓得嚴嚴實實,確實