2013-08-26 30 views
-1

當我在任務管理器中查看我的進程的GDI對象數時,我發現並非每個GDI對象函數DeleteObject()的調用都會導致此數字遞減,該函數調用不會返回FALSE(因爲它應該在對象刪除不成功的情況下)。我使用普通的Windows API GDI函數,沒有額外的庫和包裝器,如MFC。爲什麼會出現這種情況,這是否意味着GDI資源泄漏?刪除GDI對象不會減少它們的編號

下面是代碼如何重現問題:

void gditest() 
{ 
    HBRUSH h = CreateSolidBrush(RGB(255, 237, 5)); 
    HRGN rgn = CreateRectRgn(0, 100, 100, 0); 

    FillRgn(g_DC, rgn, h); 

    int before = GetGuiResources(GetCurrentProcess(), GR_GDIOBJECTS); 
    int rs = DeleteObject(h); 
    if (!rs) 
     throw; 
    int after = GetGuiResources(GetCurrentProcess(), GR_GDIOBJECTS); 
} 

變量「之前」和「之後」是相等的。 g_DC是主窗口的HDC。

+0

請提供一個SSCCE –

+4

標準的錯誤仍然是在設備上下文中選擇對象。是的,這是一個泄漏。 –

+0

在這種情況下,DeleteObject()不應該返回零嗎?刪除對象的MSDN:「如果指定的句柄無效或當前選擇到DC中,則返回值爲零。」 –

回答

1

股票GDI對象從不創建也不銷燬。它們由Windows維護,您可以根據需要使用它們。如果您的代碼如下所示

HPEN hPen = (HPEN)GetStockObject(BLACK_PEN); 
DeleteObject(hPen); 

您不會看到GDI計數增加或減少。對DeleteObject的調用將返回TRUE,即使該對象未被真正刪除。

如果您想檢查資源泄漏,您可以在代碼中調用GetGuiResources來比較前/後值。您通常會將資源計數應匹配的那些調用置於資源匹配的位置,即創建和銷燬資源匹配。

+0

我不認爲你應該在股票對象上調用'DeleteObject'。 –

+1

@Ben這是沒有必要的,但它[也沒有害處](http://msdn.microsoft.com/en-us/library/windows/desktop/dd144925.aspx)。 – IInspectable

+0

@IInspectable:在調試器中,DeleteObject()被越過,返回非零值,但TaskMan中GDI對象的數量保持不變。 =(DeleteObject對同一對象的第二次調用失敗 –

0

在刪除對象之前,您應該選擇一個NULL對象到設備上下文。

實施例:

選擇對象(g_DC,GetStockObject(NULL_BRUSH)); DeleteObject(h);