Visual c++ GDI资源泄漏

Visual c++ GDI资源泄漏,visual-c++,memory-leaks,gdi,Visual C++,Memory Leaks,Gdi,我在我们庞大的应用软件中发现了GDI漏洞 下面是一个简单的程序来测试这个问题。 其思想是主对话框打开另一个对话框(对话框A)。 如果对话框包含CStatic控件的位图功能, 它会造成GDI泄漏 甚至当我使用“删除对象(位图)”时 我做错什么了吗? 你有什么想法吗 谢谢 // Resource File ... DIALOG_BOXA DIALOGEX 0, 0, 219, 142 STYLE DS_SETFONT | DS_FIXEDSYS | WS_POPUP | WS_VISIBLE |

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

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

甚至当我使用“删除对象(位图)”时

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

谢谢

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

以下是静态控制中GDI泄漏的解释和解决方案:
这很复杂。首先,让我们仔细看看你的代码

bitmap = LoadBitmap ( AfxGetApp()->m_hInstance,BEACON_BIG_RED_ON) ;
m_static.SetBitmap (bitmap );
DeleteObject(bitmap);
您不应该删除刚刚告诉静态控件要使用的位图。它还在使用它!它将继续使用它,直到您将位图设置为其他内容

因此,与其在对话框初始化期间尝试删除位图,不如等到对话框被销毁。此时,必须通知静态控件停止使用位图,然后才能删除位图对象

其次,静态控件有时会复制位图。它是否复制取决于一系列因素,包括位图是否具有非零alpha通道。销毁此副本也是您的问题。(这可能就是您的一个案例有效而另一个无效的原因。)


基本上,您必须跟踪您认为已设置的位图,直到需要清理为止。然后你必须比较静态控件中的实际内容和你认为给它的内容。如果它们不同,那么您将同时销毁它们(位图和静态控件副本)。如果它们是相同的,那么静态控件没有创建副本,您必须只销毁您创建的副本(一次!)。

您是如何确定存在泄漏的?此外,MSDN声明您应该使用LoadImage而不是LoadBitmap。。。你试过改变吗?谢谢你的回复。是的,我使用“GDIView”和“Windows任务管理器”来监视这个,我发现在打开“DialogBoxA”后“GDI对象”增加了。谢谢,我尝试了“LoadImage”,同样的问题。打开对话框时,GDI对象应该增加。试着注释你的代码行,你可能会发现它做了同样的事情。。。你认为他们是怎么画这些按钮的!!??