【问题标题】:C++ GDI+ Objects Memory leak/too many objects?C++ GDI+ 对象内存泄漏/对象太多?
【发布时间】:2015-10-06 22:43:39
【问题描述】:

我一直在制作一个 c++ 绘图程序,并且我有一部分是在函数内部使用 gdi+ 进行绘图的,所以我每次调用函数时都需要声明我的图形对象。这显然是错误的,并且会在某处导致泄漏,所以之后有些调用它会变慢,然后突然停止绘制,正如预期的那样。

我试图在每次完成绘制时清除我的对象,但它似乎并没有解决问题。我想也许 PEN 对象是问题的一部分,但一些见解会非常有帮助 我的代码:

void function()
{
    DWORD pdwGduStartup;
    GdiplusStartupInput GdiStartupInp;
    GdiplusStartup(&pdwGduStartup, &GdiStartupInp, NULL);
    Pen pnPen_Blue(Gdiplus::Color(255, 0, 0, 255), 2.0F);
    Pen pnPen_Green(Gdiplus::Color(255, 255, 0, 255), 2.0F);


    LPCSTR LGameWindow = "MyWindow";
    HWND hGameWindow = FindWindow(NULL, LGameWindow);
    Graphics graphics(GetDC(hGameWindow));
for (int n=10; n>0; n--)
    graphics.DrawLine(&pnPen_Green,0, 0, 0, n);
    GdiplusShutdown(pdwGduStartup);
    graphics.Flush();
}

非常感谢!

编辑:添加的发布 DC 没有做任何事情!

DWORD pdwGduStartup;
GdiplusStartupInput GdiStartupInp;
GdiplusStartup(&pdwGduStartup, &GdiStartupInp, NULL);
Pen pnPen_Blue(Gdiplus::Color(255, 0, 0, 255), 2.0F);
Pen pnPen_Green(Gdiplus::Color(255, 255, 0, 255), 2.0F);


LPCSTR LGameWindow = "MyWindow";
HWND hGameWindow = FindWindow(NULL, LGameWindow);
HDC GDC = GetDC(hGameWindow);
Graphics graphics(GDC);
ReleaseDC(hGameWindow, GDC);
GdiplusShutdown(pdwGduStartup);
graphics.Flush();

我的 GDI 对象仍然上升到 10,000 个!

【问题讨论】:

  • 我可能弄错了,但我认为 Pen 类析构函数应该删除它使用的任何内部 GDI 对象。
  • @jensa,但我怎么能摧毁它呢? en.cppreference.com/w/cpp/language/destructor
  • 您永远不会显式调用对象析构函数,当对象超出范围时,该语言会为您执行此操作。在这种特殊情况下,当函数结束时。
  • 调用 ReleaseDC 并不意味着你正在清理 GDI 对象。
  • 那我该怎么做呢?

标签: c++ memory-leaks gdi+


【解决方案1】:

必须在删除所有 GDI+ 对象后调用 GdiplusShutdown。在您的代码中,当对象超出范围时,在 GdiplusShutdown 之后调用 Pen 和 Graphics 析构函数。

【讨论】:

    【解决方案2】:

    我猜问题出在GetDC。您应该调用 ReleaseDC 或使用 WTL 智能指针。

    我记得这些东西很容易用任务管理器调试。它显示进程的 HANDLE 计数和 GDI 对象计数,因此您可以看到哪些行生成了新对象。

    【讨论】:

    • 它最多可以处理 10,000 个对象并停止工作.. 我似乎无法释放 DC
    • 10,000 个对象是一个限制,超过此限制后它将停止工作。您应该尝试调试您的代码并跟踪新 gdi 对象的创建时间。您可以在任务管理器(选择列 -> GDI 对象)或进程资源管理器中查看 GDI 对象计数。
    • 您可以尝试注释整个代码并逐行测试它。
    • 找到什么?我不知道什么通常会删除对象
    • 首先要确保泄漏在你的函数内部。尽量只保留 GdiPlus 启动/关闭功能。然后添加查找窗口。然后画线。
    【解决方案3】:

    我没有对我的 GDI+ 进行逻辑编码。在逻辑中首先你需要创建图形对象,然后循环绘制它。其他任何事情都是错误的,代码无法修复它!

    【讨论】:

      【解决方案4】:

      尝试这样的事情,使用完成后可以轻松删除的指针。

      DWORD pdwGduStartup;
      GdiplusStartupInput GdiStartupInp;
      GdiplusStartup(&pdwGduStartup, &GdiStartupInp, NULL);
      Pen pnPen_Blue* = new Pen(Gdiplus::Color(255, 0, 0, 255), 2.0F);
      Pen pnPen_Green* = new Pen(Gdiplus::Color(255, 255, 0, 255), 2.0F);
      
      LPCSTR LGameWindow = "MyWindow";
      HWND hGameWindow = FindWindow(NULL, LGameWindow);
      HDC GDC = GetDC(hGameWindow);
      Graphics* g = new Graphics(GDC);
      
      // Do stuff here
      
      ReleaseDC(hGameWindow, GDC);
      delete pnPen_Blue;
      delete pnPen_Green;
      g->Flush();
      delete g;
      delete GDC; // not sure
      GdiplusShutdown(pdwGduStartup);
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-06-20
        • 2012-10-31
        • 2012-01-08
        • 2012-05-15
        • 2012-09-12
        • 1970-01-01
        • 2017-06-20
        • 1970-01-01
        相关资源
        最近更新 更多