【问题标题】:How To Handle GDI Resource Leak如何处理 GDI 资源泄漏
【发布时间】:2011-12-23 14:59:28
【问题描述】:

在我的应用程序中,我使用 GetDC 获取 DC,并且还使用 ReleaseDC 释放该 DC。

但是当我使用 VTune 分析我的应用程序时,它在 GetDC 显示 GDIResource 泄漏。

m_hdc = ::GetDC(hWndDisplay[frameIndex]);
::SetStretchBltMode(m_hdc,STRETCH_DELETESCANS);
::StretchDIBits(m_hdc,0,0,IMAGE_WIDTH,IMAGE_HEIGHT,0,0,imageWidth,imageHeight,rgbavpg,pTempBmpInfo,DIB_RGB_COLORS,SRCCOPY);
::ReleaseDC(hWndDisplay[frameIndex],m_hdc);

以下是相关代码: m_hdc id 全局定义为 HDC m_hdc;

void Display(unsigned char *rgbavpg,unsigned long imageSize, unsigned int imageWidth, unsigned int imageHeight, unsigned int frameIndex)
{

PBITMAPINFO pTempBmpInfo = NULL;
DWORD timespan;
int temp;

if ((IMAGE_WIDTH==imageWidth)&&(IMAGE_HEIGHT==imageHeight))
{
    frameNum++ ;
}
timespan = 1000/15;
DWORD diff = GetTickCount() - tickes[frameIndex];//lvm4;
tickes[frameIndex]=GetTickCount();
if (g_threadMarkedForStop[frameIndex] == TRUE ) 
{        
    return;
}
if(diff < timespan)
    { 
            Sleep(diff);
    }
if (FALSE == ::IsWindow(hWndDisplay[frameIndex])) 
{
    g_threadMarkedForStop[frameIndex] = TRUE
    return;
}

pTempBmpInfo = &m_bmpinfo[frameIndex];
if(pTempBmpInfo != NULL)
{
    pTempBmpInfo->bmiHeader.biWidth= imageWidth ;
    pTempBmpInfo->bmiHeader.biHeight= imageHeight;
}
else 
{
    g_threadMarkedForStop[frameIndex] = TRUE;

    return;
}
m_hdc = ::GetDC(hWndDisplay[frameIndex]);
     ::SetStretchBltMode(m_hdc,STRETCH_DELETESCANS);

if (true == fullscreen)                ::StretchDIBits(m_hdc,0,0,510,320,0,0,imageWidth,imageHeight,rgbavpg,pTempBmpInfo,DIB_RGB_COLORS,SRCCOPY);
else
{       ::StretchDIBits(m_hdc,0,0,IMAGE_WIDTH,IMAGE_HEIGHT,0,0,imageWidth,imageHeight,rgbavpg,pTempBmpInfo,DIB_RGB_COLORS,SRCCOPY);
    //::SetDIBitsToDevice(m_hdc,0,0,IMAGE_WIDTH,IMAGE_HEIGHT,0,0,0,imageHeight,rgbavpg,pTempBmpInfo,DIB_RGB_COLORS);
}
::ReleaseDC(hWndDisplay[frameIndex],m_hdc);
}

请帮我解决这个问题。

【问题讨论】:

  • sn-p 中没有明显的泄漏。为什么 m_hdc 是您班级的成员?这不可能。
  • 感谢您的回复。那么 m_hdc 是全局定义的 HDC 类型的句柄。您能否详细说明为什么您认为这不正确?
  • 我假设 Hans 的观点是,一旦您不再需要 DC,就应该使用和处理掉它们。它们是内存/资源消耗的,选择到它们中的 bmp 不能被删除,所以让它们到处乱放通常是错误的做法。

标签: visual-c++ gdi


【解决方案1】:

尽管使用了成员变量 m_hdc 而没有使用局部变量,但这段代码本身看起来不错。

您是否看到 VTune 标记每次或仅偶尔泄漏?

当我看到您对 IsWindow() 的调用和变量名称 g_threadMarkedForStop 时,我想知道您是否正在执行多线程。会不会是在 GetDC 和 ReleaseDC 之间有时会破坏窗口?

【讨论】:

  • 感谢您的回复...实际上我的应用程序通过逐帧解码编解码器来显示一个或多个视频缩略图。VTune 显示没有泄漏以显示一个视频缩略图,但对于一个以上的视频缩略图它是在 m_hdc = ::GetDC(hWndDisplay[frameIndex]) 处显示 GDIResource 泄漏;即使我正在发布它,正如你所看到的,我已经使用了 ReleaseDC。是的,我已经完成了多线程来显示一个或多个缩略图。而且我不会破坏 GetDC 和 ReleaseDC 之间的窗口。有没有其他可能的方式来释放 DC?请尽快回复。感谢和问候 Mayank
  • 在这种情况下,我会 1) 将 m_hdc 更改为局部变量,以确保您不会从任何地方更改 m_hdc;2) 检查 ReleaseDC 的返回值,以确保 Windows 确实释放了 DC。如果在这两个更改之后 VTune 仍然抱怨,您可能会忽略 VTune 错误消息。
  • 谢谢 Werner,我的问题现在解决了。现在我已经在本地声明了 m_hdc,它正在工作。但是我仍然想问你,当我被声明为 Globally 时,GDIResource 泄漏的原因是什么?再次非常感谢您....
  • 我不知道。您是否在其他任何地方使用了 m_hdc 或无意中覆盖了它?如果不是,那么我能想到的唯一原因是您从两个线程并行调用 Display()(可能针对不同的 frameIndex),而一个线程只设置 m_hdc 和 StretchDIBits,另一个线程覆盖了 m_hdc,从而导致第一个 DC没有被释放,第二个 DC 被释放了两次。
  • 感谢您的回复。不,我没有在其他任何地方使用 m_hdc 或覆盖它。是的,我认为您是对的,它两次发布了第二个 DC,而第一个没有发布,是否显示 GDIResource 泄漏。谢谢你和问候 Mayank...
猜你喜欢
  • 2014-02-10
  • 1970-01-01
  • 2019-06-15
  • 2010-09-16
  • 2011-05-05
  • 2010-10-26
  • 2016-07-07
  • 2020-11-11
  • 1970-01-01
相关资源
最近更新 更多