GDI资源泄漏

时间:2014-01-21 00:30:44

标签: visual-c++ memory-leaks gdi

我在我们庞大的应用软件中发现了GDI泄漏。

下面是一个测试此问题的简单程序。 想法是主对话框打开另一个对话框(对话框A)。 如果对话框A包含CStatic控件的位图功能, 它会造成GDI泄漏。

即使我使用“DeleteObject(bitmap)”。

我做错了什么吗? 你有什么想法吗?

感谢。

// 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
}

2 个答案:

答案 0 :(得分:1)

以下是静态控制中GDI泄漏的exlanantion和解决方案: http://blogs.msdn.com/b/oldnewthing/archive/2014/02/19/10501282.aspx

答案 1 :(得分:0)

这很复杂。首先,让我们仔细看看您的代码

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

您应该删除您刚刚告诉静态控件使用的位图。它还在使用它!在您将位图设置为其他内容之前,它将继续使用它。

因此,不要在对话框初始化期间尝试删除位图,而应该等到对话框被销毁。此时,您必须告诉静态控件停止使用位图,然后才能删除位图对象。

其次,静态控件有时会复制您的位图。它是否复制取决于一堆事物,包括位图是否具有非零alpha通道。破坏此副本也成为您的问题。 (这可能就是为什么你的一个案件有效,另一个没有。)

您基本上必须跟踪您认为设置的位图,直到清理它为止。然后你必须比较静态控件中的实际内容与你认为的那个。如果它们不同,则会破坏它们(您的位图和静态控件副本)。如果它们相同,那么静态控件不会复制,你必须销毁你制作的那个(一次!)。