有没有办法可以删除HBITMAP而不是使用DeleteObject()?

我正在编写一些代码来帮助跟踪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)

2 years ago

好 . 仔细查看日志,并使用 GetGuiResources() 记录有多少GDI对象,看起来在创建 HICON 时会创建 HBITMAP . 但是, DestroyIcon() 函数在销毁时会绕过 DestoryObject() 函数调用 .

我想MS的某个人想通过这样做来节省几个周期?随你 .

尽管如此,这是一个有趣的练习,并且日志记录似乎运行良好 .