2017-09-20 109 views
1

我正在編寫一些代碼來幫助跟蹤GDI泄漏並更好地瞭解WINAPI。我通過繞開所有GDI functions並記錄列出的所有手柄的創建和銷燬來做到這一點。有沒有一種方法可以刪除HBITMAP而不是使用DeleteObject()?

原來,一個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 
  • 第一列是序列數(試圖訂購塞克時有用多個線程中的事件)。
  • 第二個是從第一個日誌項開始的時間(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()打得不好,並且正在使用一些未公開的功能。我將不得不調查其餘的日誌。

+0

我認爲你觀察到的是Windows操作系統的一些處理高速緩存功能。 – VuVirt

+0

@VuVirt,以及如何工作。這些不是命名對象。它將如何確定應該使用* same *句柄? – Adrian

+0

HGDIOBJ不是一個地址(意思不是唯一的),而是一些有限大小的表中的一個槽的索引。所以從技術上講,當表溢出時,你可以得到相同的HGDIOBJ值。 –

回答

1

好的。仔細查看日誌,並記錄下GetGuiResources()有多少GDI對象,看起來在創建HICON時會創建HBITMAP。但是,銷燬函數時,DestroyIcon()函數會繞過DestoryObject()函數調用。

我想MS上的某個人想要通過這樣做來節省幾個週期?隨你。

不過,這是一個有趣的練習,記錄似乎很好。

相關問題