【发布时间】:2015-05-26 13:24:03
【问题描述】:
我在理解故障转储和查找 WPF 应用程序抛出 OutOfMemoryException 的根本原因时遇到了一些麻烦。应用程序运行几个小时后抛出异常,因此这清楚地表明存在内存泄漏。
我的第一步是查看!address -summary 命令:
--- Usage Summary ---------------- RgnCount ------- Total Size -------- %ofBusy %ofTotal
<unknown> 2043 58997000 ( 1.384 Gb) 71.43% 69.22%
Heap 152 fcc3000 ( 252.762 Mb) 12.74% 12.34%
Image 1050 bc77000 ( 188.465 Mb) 9.50% 9.20%
Stack 699 7d00000 ( 125.000 Mb) 6.30% 6.10%
Free 518 3f6b000 ( 63.418 Mb) 3.10%
TEB 125 7d000 ( 500.000 kb) 0.02% 0.02%
Other 12 36000 ( 216.000 kb) 0.01% 0.01%
PEB 1 1000 ( 4.000 kb) 0.00% 0.00%
--- Type Summary (for busy) ------ RgnCount ----------- Total Size -------- %ofBusy %ofTotal
MEM_PRIVATE 2186 685b7000 ( 1.631 Gb) 84.14% 81.53%
MEM_IMAGE 1710 f3f3000 ( 243.949 Mb) 12.29% 11.91%
MEM_MAPPED 186 46db000 ( 70.855 Mb) 3.57% 3.46%
--- State Summary ---------------- RgnCount ----------- Total Size -------- %ofBusy %ofTotal
MEM_COMMIT 3366 73fe7000 ( 1.812 Gb) 93.52% 90.62%
MEM_RESERVE 716 809e000 ( 128.617 Mb) 6.48% 6.28%
MEM_FREE 518 3f6b000 ( 63.418 Mb) 3.10%
--- Protect Summary (for commit) - RgnCount ----------- Total Size -------- %ofBusy %ofTotal
PAGE_READWRITE 1650 5e19e000 ( 1.470 Gb) 75.87% 73.52%
PAGE_EXECUTE_READ 224 bc42000 ( 188.258 Mb) 9.49% 9.19%
PAGE_READWRITE|PAGE_WRITECOMBINE 28 439f000 ( 67.621 Mb) 3.41% 3.30%
PAGE_READONLY 573 3d7b000 ( 61.480 Mb) 3.10% 3.00%
PAGE_WRITECOPY 214 f8f000 ( 15.559 Mb) 0.78% 0.76%
PAGE_EXECUTE_READWRITE 265 d0a000 ( 13.039 Mb) 0.66% 0.64%
PAGE_READWRITE|PAGE_GUARD 357 33b000 ( 3.230 Mb) 0.16% 0.16%
PAGE_EXECUTE_WRITECOPY 55 119000 ( 1.098 Mb) 0.06% 0.05%
--- Largest Region by Usage ----------- Base Address -------- Region Size ----------
<unknown> 78d40000 2350000 ( 35.313 Mb)
Heap 36db0000 fd0000 ( 15.813 Mb)
Image 64a8c000 e92000 ( 14.570 Mb)
Stack 4b90000 fd000 (1012.000 kb)
Free 7752f000 1a1000 ( 1.629 Mb)
TEB 7ede3000 1000 ( 4.000 kb)
Other 7efb0000 23000 ( 140.000 kb)
PEB 7efde000 1000 ( 4.000 kb)
这说明内存相当高。
然后我用eeheap -gc 命令查看GC 堆大小。它表明堆很大(1.1GB),这表明应用程序的托管部分存在问题。
5fc90000 5fc91000 60c7acd4 0xfe9cd4(16686292)
5a060000 5a061000 5b05e9c0 0xffd9c0(16767424)
56de0000 56de1000 57ddf1c4 0xffe1c4(16769476)
57de0000 57de1000 58ddbbbc 0xffabbc(16755644)
73ff0000 73ff1000 74fe0f5c 0xfeff5c(16711516)
50de0000 50de1000 51dcfa58 0xfeea58(16706136)
5b060000 5b061000 5c05ca54 0xffba54(16759380)
4fde0000 4fde1000 50ddfd8c 0xffed8c(16772492)
Large object heap starts at 0x03921000
segment begin allocated size
03920000 03921000 049013d0 0xfe03d0(16647120)
14850000 14851000 15837380 0xfe6380(16671616)
178d0000 178d1000 1889a3e0 0xfc93e0(16552928)
1a1c0000 1a1c1000 1b1abca8 0xfeaca8(16690344)
40de0000 40de1000 41dc8b48 0xfe7b48(16677704)
42de0000 42de1000 43827170 0xa46170(10772848)
54de0000 54de1000 55dd6d18 0xff5d18(16735512)
Total Size: Size: 0x448fde94 (1150279316) bytes.
------------------------------
GC Heap Size: Size: 0x448fde94 (1150279316) bytes.
请注意,有 64 个段,每个段大约 (16MB)。似乎有一些数据保存在内存中,从未释放。
接下来我看!dumpheap -stat:
65c1f26c 207530 19092760 System.Windows.Media.GlyphRun
65c2c434 373991 20943496 System.Windows.Media.RenderData
68482bb0 746446 26872056 MS.Utility.ThreeItemList`1[[System.Double, mscorlib]]
65c285b4 746448 29857920 System.Windows.Media.DoubleCollection
64c25d58 299568 32353344 System.Windows.Data.BindingExpression
6708a1b8 2401099 38417584 System.WeakReference
67082c2c 1288315 41226080 System.EventHandler
67046f80 1729646 42238136 System.Object[]
64c1409c 206969 52156188 System.Windows.Controls.ContentPresenter
67094c9c 382163 64812664 System.Byte[]
004b0890 159 65181140 Free
64c150d0 207806 72316488 System.Windows.Controls.TextBlock
6708fd04 1498498 97863380 System.String
6848038c 847783 128775772 System.Windows.EffectiveValueEntry[]
据我了解,没有一个信号对象会占用所有内存。最大的只有大约 122MB。将所有大小(输出行的 8500 行)相加得出(1.1GB)占用的内存。似乎所有对象图都以某种方式复制并添加到内存中并且从未释放。
!gcroot 6848038c 或 !gcroot 6708fd04 检查 EffectiveValueEntry 和 System.String 是如何可达的,永无止境,堆栈太大了...
dumpheap -mt <address> 没有向我展示令我震惊的东西。 !finalizequeue 表明有许多对象(超过 200 万个)注册完成:
6708a1b8 2401099 38417584 System.WeakReference
Total 2417538 objects
我怀疑OutOfMemoryException 是在应用程序尝试复制对象图并分配新内存时出现的,但我找不到它的根本原因。
问题我怎样才能深入到问题的根源(我可以使用什么其他的windbg命令来检查它)。似乎不仅仅是一个对象在泄漏,而是整个对象图都在泄漏。我是在正确的轨道上还是我忽略了其他东西?还有什么其他假设?
【问题讨论】:
-
也可以尝试使用 CLR Profiler,它可以很容易地为您提供很多复杂的信息。您可以使用
!TraverseHeap为CLR Profiler 导出必要的日志。最重要的是,它使显示对象分配图变得非常容易。但是,我担心它可能对您没有帮助 - 我认为 WPF 本身存在一些烦人的内存泄漏,环顾四周可能会帮助您找到这个问题。 -
@Luaan 不幸的是,我只有故障转储,可以进行事后调试。无论如何,感谢 CLR 提供商的成功。
!TraverseHeap命令是特定于 CLR Profiler 的吗? -
您可以将
!TraverseHeap生成的文件加载到CLR Profiler 中,因此故障转储就足够了——在WinDbg 中打开它,运行!TraverseHeap,然后在CLR Profiler 中打开生成的文件。您也可以自己解析文件,它是一个简单的文本文件。 -
但它位于不同的模块中,因为仅加载了 SOS,我就进入了 windbg“未找到导出 TraversHeap”错误
-
它可能在 SOSex 中。尝试谷歌搜索,我相信你会发现什么是错的。哦,确保你指定一个文件名作为参数。
标签: wpf debugging memory-leaks windbg dump