我有一个崩溃转储,我怀疑GDI泄漏是造成崩溃的原因
从完整的崩溃转储中可以找出崩溃时我的进程使用的GDI句柄数量?
答案 0 :(得分:2)
不太可能,因为自g2任务以来唯一的调试器扩展gdikdx.dll没有得到积极维护,因为w2k版本并且我相信它们已经停止发货,因为不是很多人都在攻击gdi内部 - 根据某人的声明我在一个新闻组中偶然发现 - 因此不再投入。 您只剩下几个选项,遗憾的是所有这些选项都是关于运行时故障排除的。
您可以从像nirsoft的GDIView这样的工具开始,监控应用程序中GDI资源的使用情况,然后进入任何运行时检测选项:
P.S。您是否可以更具体地了解特定事故的实际原因?
答案 1 :(得分:2)
我创建了一个Windbg脚本来从GDI Handle表中转储所有GDI句柄。见https://aloiskraus.wordpress.com/2016/06/25/show-gdi-handles-by-type-in-windbg/
当您转储时,例如两次你可以看到那里发生了什么变化:
0:013> $$>a<"D:\GdiDump\DumpGdi.txt"
GDI Handle Table 00000000013e0000 0000000001561000
GDI Handle Count 14
DeviceContexts: 4
Regions: 2
Bitmaps: 2
Palettes: 0
Fonts: 3
Brushes: 3
Pens: 0
Uncategorized: 0
0:013> g
0:014> $$>a<"D:\GdiDump\DumpGdi.txt"
GDI Handle Table 00000000013e0000 0000000001561000
GDI Handle Count 1021
DeviceContexts: 8
Regions: 3
Bitmaps: 1003
Palettes: 0
Fonts: 3
Brushes: 4
Pens: 0
Uncategorized: 0
这是脚本
$$ Run as: $$>a<DumpGdi.txt
$$ Written by Alois Kraus 2016
$$ uses pseudo registers r0-5 and r8-r14
r @$t1=0
r @$t8=0
r @$t9=0
r @$t10=0
r @$t11=0
r @$t12=0
r @$t13=0
r @$t14=0
$$ Increment count is 1 byte until we find a matching field with the current pid
r @$t4=1
r @$t0=$peb
$$ Get address of GDI handle table into t5
.foreach /pS 3 /ps 1 ( @$GdiSharedHandleTable { dt ntdll!_PEB GdiSharedHandleTable @$t0 } ) { r @$t5 = @$GdiSharedHandleTable }
$$ On first call !address produces more output. Do a warmup
.foreach /pS 50 ( @$myStartAddress {!address @$t5} ) { }
$$ Get start address of file mapping into t2
.foreach /pS 4 /ps 40 ( @$myStartAddress {!address @$t5} ) { r @$t2 = @$myStartAddress }
$$ Get end address of file mapping into t3
.foreach /pS 7 /ps 40 ( @$myEndAddress {!address @$t5} ) { r @$t3 = @$myEndAddress }
.printf "GDI Handle Table %p %p", @$t2, @$t3
.for(; @$t2 < @$t3; r @$t2 = @$t2 + @$t4)
{
$$ since we walk bytewise through potentially invalid memory we need first to check if it points to valid memory
.if($vvalid(@$t2,4) == 1 )
{
$$ Check if pid matches
.if (wo(@$t2) == @$tpid )
{
$$ increase handle count stored in $t1 and increase step size by 0x18 because we know the cell structure GDICell has a size of 0x18 bytes.
r @$t1 = @$t1+1
r @$t4 = 0x18
$$ Access wType of GDICELL and increment per GDI handle type
.if (by(@$t2+6) == 0x1 ) { r @$t8 = @$t8+1 }
.if (by(@$t2+6) == 0x4 ) { r @$t9 = @$t9+1 }
.if (by(@$t2+6) == 0x5 ) { r @$t10 = @$t10+1 }
.if (by(@$t2+6) == 0x8 ) { r @$t11 = @$t11+1 }
.if (by(@$t2+6) == 0xa ) { r @$t12 = @$t12+1 }
.if (by(@$t2+6) == 0x10 ) { r @$t13 = @$t13+1 }
.if (by(@$t2+6) == 0x30 ) { r @$t14 = @$t14+1 }
}
}
}
.printf "\nGDI Handle Count %d", @$t1
.printf "\n\tDeviceContexts: %d", @$t8
.printf "\n\tRegions: %d", @$t9
.printf "\n\tBitmaps: %d", @$t10
.printf "\n\tPalettes: %d", @$t11
.printf "\n\tFonts: %d", @$t12
.printf "\n\tBrushes: %d", @$t13
.printf "\n\tPens: %d", @$t14
.printf "\n\tUncategorized: %d\n", @$t1-(@$t14+@$t13+@$t12+@$t11+@$t10+@$t9+@$t8)
答案 2 :(得分:0)