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

时间:2017-09-20 15:29:25

标签: winapi

我正在编写一些代码来帮助跟踪GDI泄漏并更好地理解WINAPI。我这样做是通过绕过所有GDI functions并记录所列出的所有句柄的创建和销毁。

原来使用HBITMAP正在创建CreateDIBitmap()并且未使用DeleteObject()(或列出的任何其他销毁函数调用)销毁,然后在某个时间后CreateBitmap() 1}}调用与前面提到的函数相同的句柄。在它们之间创建了很多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列是序列计数(在尝试在多个线程中排序事件序列时很有用)。
  • 第二个是第一个日志项的时间(毫秒)。
  • : 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()不能正常运行并使用一些未记录的函数。我将不得不调查其余的日志。

1 个答案:

答案 0 :(得分:1)

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

我想MS的某个人想通过这样做来节省几个周期?不管。

尽管如此,这是一项有趣的练习,而且日志记录看起来效果很好。