直接调用GetDC会造成内存泄漏吗?

med*_*med 2 c++ mfc gdi

我正在监听ON_WM_ERASEBKGND()与该事件相关的已触发函数内的消息OnEraseBackground(CDC* pDC). 我正在更改背景颜色,如下所示:

if (pDC)
{
    pDC->SetBkColor(BlackColor);        
}
else if (GetDC())
{
    GetDC()->SetBkColor(BlackColor);            
}
Run Code Online (Sandbox Code Playgroud)

我的问题是,我应该ReleaseDC()在之后打电话GetDC()吗?

And*_*kle 5

Win32 API

根据这篇文章,GetDC它指出:

使用公共DC绘制后,必须调用ReleaseDC该函数来释放DC。私有DC不必释放。必须从调用 的同一线程中调用。DC 的数量仅受可用内存的限制。ReleaseDCGetDC


CWnd

如果是的CWnd::GetDC话:

除非设备上下文属于一个窗口类,否则在绘制之后必须调用ReleaseDC该成员函数来释放上下文。


正常情况下你会这样做:

CDC *pDC = GetDC();
if (pDC != nullptr)
{
   pDC->SomeFunc(...);
}
// etc..
Run Code Online (Sandbox Code Playgroud)

链接的文章引用了此处的一些示例。

这有帮助吗?


IIn*_*ble 5

GetDC从or返回的设备上下文应该始终通过将其传递给or (无论是哪一个)CWnd::GetDC来释放。该文档对于并非严格必要的情况相当宽松,尽管建立这些先决条件本身很复杂。ReleaseDCCWnd::ReleaseDC

ReleaseDC如果您在并不严格需要释放的设备上下文上调用任一函数,则该操作不会产生不利影响。

不释放设备上下文(GDI 资源)的后果比内存泄漏严重得多。GDI 资源受到严格限制,并且在同一用户会话中运行的所有进程之间共享。一个程序的 GDI 资源泄漏很容易导致任何其他程序出现故障。

请注意,您在代码中调用了GetDC 两次,因此您也需要释放它两次。或者,只调用一次,例如

if (pDC)
{
    pDC->SetBkColor(BlackColor);        
}
else
{
    auto myDC = GetDC();
    myDC->SetBkColor(BlackColor);
    ReleaseDC(myDC);
}
Run Code Online (Sandbox Code Playgroud)

或者,使用带初始值设定项的if语句(C++17 中引入):

if (pDC)
{
    pDC->SetBkColor(BlackColor);        
}
else if (auto myDC = GetDC())
{
    myDC->SetBkColor(BlackColor);
    ReleaseDC(myDC);
}
Run Code Online (Sandbox Code Playgroud)

不过,实际上,我可能会报废整个else手臂。如果您的WM_ERASEBKGND消息处理程序没有收到设备上下文,那么就没有理由自己去寻找设备上下文。