【问题标题】:Deleting GDI objects does not decrease their number删除 GDI 对象不会减少它们的数量
【发布时间】:2013-08-26 15:53:33
【问题描述】:

当我在任务管理器中查看我的进程的 GDI 对象数量时,我发现并非每次调用 GDI 对象的函数 DeleteObject() 都会导致该数量减少,并且函数调用不会返回 FALSE (如果对象删除不成功,则应该这样做)。我使用的是普通的 Windows API GDI 函数,没有额外的库和包装器,例如 MFC。为什么会出现这种情况,是否意味着GDI资源泄漏?

这里是如何重现问题的代码:

void gditest()
{
    HBRUSH h = CreateSolidBrush(RGB(255, 237, 5));
    HRGN rgn = CreateRectRgn(0, 100, 100, 0);

    FillRgn(g_DC, rgn, h);

    int before = GetGuiResources(GetCurrentProcess(), GR_GDIOBJECTS);
    int rs = DeleteObject( h );
    if ( !rs )
        throw;
    int after = GetGuiResources(GetCurrentProcess(), GR_GDIOBJECTS);
}

变量“之前”和“之后”是相等的。 g_DC 是主窗口的 HDC。

【问题讨论】:

  • 请提供SSCCE
  • 标准错误仍然是在设备上下文中选择对象。是的,这是一个泄漏。
  • 在这种情况下 DeleteObject() 不应该返回零吗? DeleteObject 的 MSDN:“如果指定的句柄无效或当前被选入 DC,则返回值为零。”
  • 一个DC也是一个GDI对象,你是在调用ReleaseDC同时删除画笔吗?
  • 每次调用GDI函数后是否需要释放DC?我在程序启动时为主窗口初始化了一个全局 DC 句柄,所有功能都只使用这个 DC。 (程序是单线程的。)

标签: c++ windows winapi gdi


【解决方案1】:

Stock GDI 对象永远不会被创建或销毁。它们由 Windows 维护,您可以随意使用它们。如果你有如下代码

HPEN hPen = (HPEN)GetStockObject(BLACK_PEN);
DeleteObject(hPen);

您不会看到 GDI 计数上升或下降。对 DeleteObject 的调用将返回 TRUE,即使该对象并未真正删除。

如果您想检查资源泄漏,您可以在代码中调用GetGuiResources 来比较之前/之后的值。您通常会将这些调用放在资源计数应该匹配的位置,即资源的创建和销毁匹配。

【讨论】:

  • 我认为你不应该在股票对象上调用DeleteObject
  • @Ben 没必要,不过是not harmful either
  • @IInspectable:在调试器中,DeleteObject() 被单步执行,返回非零,但 TaskMan 中 GDI 对象的数量保持不变。 =(并且对同一对象的第二次 DeleteObject 调用失败。
  • 补充:GetGuiResources 返回与TaskMan 相同的数字,并且DeleteObject() 前后返回的数字也没有变化。 =(
【解决方案2】:

您应该在删除对象之前为设备上下文选择一个 NULL 对象。

例子:

SelectObject(g_DC, GetStockObject(NULL_BRUSH)); 删除对象(h);

【讨论】:

    猜你喜欢
    • 2014-09-02
    • 1970-01-01
    • 2013-01-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多