【问题标题】:Does calling GetDC directly create memory leaks?直接调用 GetDC 会造成内存泄漏吗?
【发布时间】:2022-10-12 22:18:09
【问题描述】:

我正在收听ON_WM_ERASEBKGND() msg,在与名为OnEraseBackground(CDC* pDC) 的事件相关的触发函数中。我正在更改如下背景颜色:

if (pDC)
{
    pDC->SetBkColor(BlackColor);        
}
else if (GetDC())
{
    GetDC()->SetBkColor(BlackColor);            
}

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

【问题讨论】:

  • Err ...,我不明白为什么要覆盖 OnEraseBackground 只是为了设置背景颜色。对于自定义窗口类,您可以通过使用AfxRegisterWndClass 来设置一次(在创建窗口之前)以注册具有特定背景颜色的自定义 WindowClass...

标签: c++ mfc gdi


【解决方案1】:

Win32 API

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

用普通DC作画后,ReleaseDC函数必须调用释放 DC。班级私人的DCs不要必须被释放。 ReleaseDC 必须从调用GetDC 的同一线程中调用。 DC 的数量仅受可用内存的限制。


CWnd

如果是CWnd::GetDC,那么:

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


在正常情况下,您会这样做:

CDC *pDC = GetDC();
if (pDC != nullptr)
{
   pDC->SomeFunc(...);
}
// etc..

链接的文章参考了一些示例here

这有帮助吗?

【讨论】:

    【解决方案2】:

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

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

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

    请注意,您拨打的是GetDC两次在您的代码中,因此您也希望将其发布两次。或者,只调用一次,例如

    if (pDC)
    {
        pDC->SetBkColor(BlackColor);        
    }
    else
    {
        auto myDC = GetDC();
        myDC->SetBkColor(BlackColor);
        ReleaseDC(myDC);
    }
    

    或者,使用带有初始化程序的if statement(在 C++17 中引入):

    if (pDC)
    {
        pDC->SetBkColor(BlackColor);        
    }
    else if (auto myDC = GetDC())
    {
        myDC->SetBkColor(BlackColor);
        ReleaseDC(myDC);
    }
    

    不过,真的,我可能会废弃整个else-arm。如果您的WM_ERASEBKGND 消息处理程序没有收到设备上下文,那么没有理由自己去寻找一个。

    【讨论】:

      猜你喜欢
      • 2019-03-21
      • 1970-01-01
      • 2014-05-13
      • 2018-08-13
      • 2013-09-03
      • 1970-01-01
      • 1970-01-01
      • 2020-04-17
      • 1970-01-01
      相关资源
      最近更新 更多