2014-01-21 86 views
0

我在我們龐大的應用軟件中發現了GDI泄漏。GDI資源泄漏

下面是一個簡單的程序來測試這個問題。 想法是主對話框打開另一個對話框(對話框A)。 如果對話框A包含CStatic控件的位圖函數,則它將創建GDI泄漏。

即使當我使用「DeleteObject(位圖)」。

我做錯了什麼? 你有什麼想法嗎?

謝謝。

// Resource File 
... 

DIALOG_BOXA DIALOGEX 0, 0, 219, 142 
STYLE DS_SETFONT | DS_FIXEDSYS | WS_POPUP | WS_VISIBLE | WS_BORDER 
EXSTYLE WS_EX_STATICEDGE 
FONT 8, "MS Shell Dlg", 400, 0, 0x1 
BEGIN 
    DEFPUSHBUTTON "OK",IDOK,46,121,50,14 
    PUSHBUTTON  "Cancel",IDCANCEL,119,121,50,14 
    CONTROL   131,RED_LIGHT0,"Static",SS_BITMAP,7,17,80,37 
    PUSHBUTTON  "",RED_LIGHT1,7,60,80,37,BS_BITMAP | NOT WS_TABSTOP 
END 

// head file 
DialogBoxA: public CDialog 
{ 
    ... 

    CStatic m_static; 
    CButton m_button ; 

    ... 
} 


///////////////////////////////////////////////////////// 

void DialogBoxA::DoDataExchange(CDataExchange* pDX) 
{ 
    CDialog::DoDataExchange(pDX); 
    DDX_Control(pDX, RED_LIGHT0, m_static); 
    DDX_Control(pDX, RED_LIGHT1, m_button); 
} 

BOOL DialogBoxA::OnInitDialog() 
{ 
    CDialog::OnInitDialog(); 

    HBITMAP bitmap ; 

    // This will create GDI leak !!! 
    bitmap = LoadBitmap (AfxGetApp()->m_hInstance,BEACON_BIG_RED_ON) ; 
    m_static.SetBitmap (bitmap); 
    DeleteObject(bitmap); 


    // This is OK !!! 
    bitmap = LoadBitmap (AfxGetApp()->m_hInstance,BEACON_BIG_RED_ON) ; 
    m_button.SetBitmap (bitmap); 
    DeleteObject(bitmap); 

    return TRUE; // return TRUE unless you set the focus to a control 
       // EXCEPTION: OCX Property Pages should return FALSE 
} 
+0

您是如何建立泄漏的? – noelicus

+0

此外,MSDN指出你應該使用LoadImage而不是LoadBitmap ......你有沒有試過改變它? – noelicus

+0

謝謝你的回覆。是的,我使用「GDIView」和「Windows任務管理器」來監視這個,我發現打開「DialogBoxA」後增加了「GDI對象」。 – ybc45

回答

0

很複雜。首先,讓我們看看你的代碼

bitmap = LoadBitmap (AfxGetApp()->m_hInstance,BEACON_BIG_RED_ON) ; 
m_static.SetBitmap (bitmap); 
DeleteObject(bitmap); 

你應該刪除您剛纔告訴靜態控件使用位圖仔細看看。它仍在使用它!它將繼續使用它,直到您將位圖設置爲其他內容。

因此,不要試圖在對話框初始化期間刪除位圖,而應該等到對話框被銷燬。此時,您必須告訴靜態控件停止使用位圖,只有這樣您才能刪除位圖對象。

二,靜態控制有時複製你的位圖。它是否進行復製取決於一系列事情,包括位圖是否具有非零的Alpha通道。它也成爲你的問題銷燬這個副本。 (這可能是爲什麼你的一個你的案例工作,而另一個沒有。)

你基本上必須跟蹤你認爲你設置的位圖,直到清理時間。然後你必須將靜態控制中的實際內容與你認爲你給的內容進行比較。如果它們不同,那麼你就會銷燬它們(你的位圖和靜態控件副本)。如果它們是相同的,那麼靜態控制就不會複製,而且你必須摧毀你製造的一個(一次!)。