我正在编写一些代码来帮助跟踪GDI泄漏并更好地理解WINAPI . 我这样做是通过绕过所有GDI functions并记录所列出的所有句柄的创建和销毁 .
事实证明 HBITMAP
正在使用 CreateDIBitmap()
创建,并且不会使用 DeleteObject()
(或列出的任何其他销毁函数调用)销毁,然后在某个时候 CreateBitmap()
调用会产生与前面提到的函数相同的句柄 . 在它们之间创建了很多 HBITMAP
(和其他句柄) .
我只是想知道是否有其他方法可以销毁未在文档中列出的 HBITMAP
?或者是否有某种方法来生成相同的 HBITMAP
?有人知道吗?
我有点担心我发现了某种GDI腐败 .
编辑
只是为了更新,这是我在日志中看到的(这只是一个实例,没有检查所有其他实例是否相同):
21133 107110: |>Creating HBITMAP # 707/782 with function CreateDIBSection
21134 107110: |<Created HBITMAP # 707/782 0xAC057A00 with function CreateDIBSection
21135 107125: |>Creating HBITMAP # 708/783 with function CreateBitmap
21136 107125: |<Created HBITMAP # 708/783 0xA9057B85 with function CreateBitmap
21137 107125: |>Creating HDC # 16/16 with function CreateCompatibleDC
21138 107125: |<Created HDC # 16/16 0x5F01466B with function CreateCompatibleDC
21139 107125: |>Creating HICON # 35/35 with function CreateIconIndirect
21140 107125: |>Creating HBITMAP # 709/784 with function CreateDIBitmap
21141 107125: |<Created HBITMAP # 709/784 0x67055812 with function CreateDIBitmap
21142 107141: |>Creating HBITMAP # 710/785 with function CreateBitmap
21143 107141: |<Created HBITMAP # 710/785 0x9605596F with function CreateBitmap
21144 107141: |>Creating HDC # 17/17 with function CreateCompatibleDC
21145 107141: |<Created HDC # 17/17 0xD7011ACD with function CreateCompatibleDC
21146 107141: |>Destroying HDC # 17/17 0xD7011ACD with function DeleteDC
21147 107156: |<Destroyed handle 0xD7011ACD with function DeleteDC
21148 107156: |<Created HICON # 35/35 0x653526D3 with function CreateIconIndirect
21149 107156: |>Destroying HBITMAP # 710/785 0xA9057B85 with function DeleteObject
21150 107156: |<Destroyed handle 0xA9057B85 with function DeleteObject
21151 107156: |>Destroying HDC # 16/16 0x5F01466B with function DeleteDC
21152 107156: |<Destroyed handle 0x5F01466B with function DeleteDC
......一段时间后(大约9秒钟)......
25319 118172: |>Creating HBITMAP # 862/937 with function CreateBitmap
25320 118172: |<Created HBITMAP # 862/937 0x9605596F with function CreateBitmap *
25321 118172: |>Creating HDC # 16/16 with function CreateCompatibleDC
25322 118172: |<Created HDC # 16/16 0x39013C5B with function CreateCompatibleDC
25323 118172: |>Creating HICON # 36/36 with function CreateIconIndirect
25324 118172: |>Creating HBITMAP # 862/937 with function CreateDIBitmap
25325 118188: |<Created HBITMAP # 862/937 0x27056374 with function CreateDIBitmap
25326 118188: |>Creating HBITMAP # 863/938 with function CreateBitmap
25327 118188: |<Created HBITMAP # 863/938 0xD20538B5 with function CreateBitmap
25328 118188: |>Creating HDC # 17/17 with function CreateCompatibleDC
25329 118188: |<Created HDC # 17/17 0xD9015812 with function CreateCompatibleDC
25330 118188: |>Destroying HDC # 17/17 0xD9015812 with function DeleteDC
25331 118188: |<Destroyed handle 0xD9015812 with function DeleteDC
25332 118203: |<Created HICON # 36/36 0x087718AD with function CreateIconIndirect
25333 118203: |>Destroying HBITMAP # 863/938 0x9605596F with function DeleteObject
25334 118219: |<Destroyed handle 0x9605596F with function DeleteObject
-
第1列是序列计数(在尝试在多个线程中排序事件序列时很有用) .
-
第二个是第一个日志项的以ms为单位的时间 .
-
:
spaces
|
是一个可视化图表,用于查看相对于我正在查看的所有调用嵌套的距离 . -
>
表示在进入函数之前,<
表示刚离开函数之后 . -
然后它说明是创建还是销毁以及正在创建或销毁的对象 .
-
x/y
其中x
是即将创建的对象的数量或销毁后存在的剩余数量,y
是相同的,除了它表示基本类型(删除的类型) . -
十六进制数是句柄值
-
然后用于创建/销毁对象的函数
-
如果该行以
*
结尾,则表示该句柄之前已经发出但尚未销毁 .
有趣的是,有多少信息以及嵌套如何工作(非常适合跟踪窗口消息) .
我注意到的另一件事是:
25349 118250: |>Destroying HICON # 36/36 0x087718AD with function DestroyIcon
25350 118250: |<Destroyed handle 0x087718AD with function DestroyIcon
HICON
被破坏了,但是包含的 HBITMAP
在日志中的任何地方再次被引用(除非它们被意外地回收) . 因此,如果这只发生在 HICON
s,则可能是 DestroyIcon()
isn 't playing nice and is using some undocumented function. I'将不得不调查其余的日志 .
1 回答
好 . 仔细查看日志,并使用
GetGuiResources()
记录有多少GDI对象,看起来在创建HICON
时会创建HBITMAP
. 但是,DestroyIcon()
函数在销毁时会绕过DestoryObject()
函数调用 .我想MS的某个人想通过这样做来节省几个周期?随你 .
尽管如此,这是一个有趣的练习,并且日志记录似乎运行良好 .