如何检测托管C#屏幕保护程序中的GDI资源泄漏?

3
这是我的问题......我怀疑我的C#屏幕保护程序存在GDI资源泄漏,仅使用托管代码。错误:“在多次操作后内存不足”。我使用VS Prof 2013 Update 4进行编译,并在Windows 7 64位下运行。我尽可能使用Dispose和非静态例程。以下是我的问题:
- 由于是屏幕保护程序,我甚至无法使用JIT debugger(应用程序加载进程停止响应)。 - Deleaker是一个C++工具,而不是C#。 - 详细的网页链接适用于Windows 9x / Windows 2000(来自2001年的MSDN杂志)或Windows 2000 / Windows XP(同样是MSDN杂志)。 - 无法下载GDIObj(显然不可用)。 - 我可以在任务管理器中显示“GDO对象”,但是屏幕保护程序在运行时使用整个屏幕并覆盖它。 - ...还有NirSoft的GDIview(Explorer.exe奇怪地具有最高数量的GDI对象)。
因此,我的问题是...
- 开发人员是否不再使用Visual Studio C#具有GDI资源泄漏的问题? - GDI+能否用于持续更新屏幕?(在仿真应用程序中) - 开发人员是否不再使用GDI / GDI+进行2.5D?(= 多层2D) - 如果是这样,哪种技术最适合仿真类型的应用程序
- 永久运行(理论上) - 定期更新整个屏幕中的某些部分(文本和图形) - 实时运行(可以容忍100毫秒差异,但必须与无线电钟保持同步)。 - 高分辨率图形(以1920x1080格式的像素为单位),即不使用DirectX的低分辨率游戏;不使用单精度GPU算术。
C#几乎很有效!
在感激您的创造性回应之际......
第一次更新
我按照以下方式在C#中实现了GetGuiResources(代码摘录):
using System.Diagnostics;
using System.Runtime.InteropServices;

static class FreeMem
{
    [DllImport("user32.dll")]
    static extern uint GetGuiResources(IntPtr hProcess, uint uiFlags);

    public static int GetGuiResourcesGDICount()
    {
        return (int)GetGuiResources(Process.GetCurrentProcess().Handle, 0);
    }

    public static int GetGuiResourcesUserCount()
    {
        return (int)GetGuiResources(Process.GetCurrentProcess().Handle, 1);
    }
}

我的应用程序显示:

  • GCIcount 在 38 到 42 之间保持稳定
  • UserCount 在 18 到 19 之间保持稳定

直到故意(由用户)引发崩溃之后,它显示:

  • GCIcount = 62
  • UserCount = 35

即没有什么戏剧性的变化。

请注意,我经常在一个 1920 x 1080 像素的位图上执行以下操作:

Graphics grTemp = Graphics.FromImage(HighlightedTZ.p_bmpC);
grTemp.DrawImage(DayNight.p_bmp, new Rectangle(0, 0, DayNight.p_bmp.Width, DayNight.p_bmp.Height));
grTemp.Dispose();

你可以尝试另一个工具,比如Jetbrains dotMemory:https://www.jetbrains.com/dotmemory/features/ - Panu Oksala
实际上,Deleaker可以调试任何二进制文件,因为它只是钩取winapi函数。但在C#的情况下,您将看不到正确的堆栈跟踪。试试禁用所有过滤器...至少可能会发现GDI泄漏的类型:HDC、HBITMAP或其他一些东西。 - Artem Razin
你确定这是GDI泄漏问题吗?如果无法使用任务管理器,请定期使用GetGuiResources并转储结果。http://www.pinvoke.net/default.aspx/user32.getguiresources - Artem Razin
尝试使用DebugDiag工具:http://www.microsoft.com/en-ca/download/details.aspx?id=42933。 - Matt
1个回答

0

您可以使用第二个系统来远程调试C#代码。

如果您只有一台计算机可用,您可以使用虚拟机系统(例如Oracle的免费Virtual Box,我推荐这个)创建第二个系统,或者其他VM软件。您需要一个有效的Windows许可证,因为即使您的VM软件正在模拟计算机,新的操作系统也会将其视为真实计算机。如果您有MSDN订阅,则可以获取额外的操作系统许可证密钥以进行调试和开发。

将您的产品放在该VM上,在VM上安装Visual Studio远程调试程序,启动它并确保您可以从主机计算机的Visual Studio访问它(通过使用主机计算机的Visual Studio附加到进程)。现在,您已经准备好进行远程调试了。

让您的屏幕保护程序在VM上启动。一旦它启动,通过使用远程调试器附加到屏幕保护程序,启动主机VS调试。现在设置断点和监视点,并像平常一样进行调试。

如果您有第二个 Windows 机器可用,则不需要虚拟机软件。只需在第二个 Windows 机器上安装产品(屏幕保护程序),安装 Visual Studio 远程调试工具集,启动远程调试器,将其设置为允许您访问它,在首选计算机的 Visual Studio 上启动,等待屏幕保护程序在第二台计算机上启动,从 Visual Studio 中附加,设置断点、观察变量,并像平常一样进行调试。


谢谢你的建议...我没有第二个Windows许可证。远程调试听起来非常有趣! - Aendie

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接