【问题标题】:Win32Exception Not enough storage is available to process this commandWin32Exception 没有足够的存储空间来处理这个命令
【发布时间】:2010-10-07 15:09:20
【问题描述】:

通过我对MaxTo 的自动崩溃收集,我得到了以下崩溃报告:

V8.12.0.0 - System.ComponentModel.Win32Exception - :Void UpdateLayered():0
Version: MaxTo8.12.0.0
Exception: System.ComponentModel.Win32Exception
Error message: Not enough storage is available to process this command
Stack trace: 
  at System.Windows.Forms.Form.UpdateLayered()
  at System.Windows.Forms.Form.OnHandleCreated(EventArgs e)
  at System.Windows.Forms.Control.WmCreate(Message& m)
  at System.Windows.Forms.Control.WndProc(Message& m)
  at System.Windows.Forms.ScrollableControl.WndProc(Message& m)
  at System.Windows.Forms.ContainerControl.WndProc(Message& m)
  at System.Windows.Forms.Form.WmCreate(Message& m)
  at System.Windows.Forms.Form.WndProc(Message& m)
  at MaxTo.MainForm.WndProc(Message& m)
  at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
  at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
  at System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)

另一个堆栈跟踪:

Version: MaxTo2009.9.0.0
Exception: System.ComponentModel.Win32Exception
Error message: Not enough storage is available to process this command
Stack trace: 
  at System.Windows.Forms.Form.UpdateLayered()
  at System.Windows.Forms.Form.OnHandleCreated(EventArgs e)
  at System.Windows.Forms.Control.WmCreate(Message& m)
  at System.Windows.Forms.Control.WndProc(Message& m)
  at System.Windows.Forms.ScrollableControl.WndProc(Message& m)
  at System.Windows.Forms.ContainerControl.WndProc(Message& m)
  at System.Windows.Forms.Form.WmCreate(Message& m)
  at System.Windows.Forms.Form.WndProc(Message& m)
  at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
  at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
  at System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)

在这个最新的堆栈跟踪中,根本没有提到 MaxTo,而且我遇到的 90% 的崩溃都与上述类似的堆栈跟踪有关。

在网上阅读我发现如果您忘记释放或处置变量,此错误很常见。在查看我的WndProc(有时似乎会出现问题)时,我找不到一个可以引用任何对象的地方。除了一个变量之外的所有变量都是 WndProc 的本地变量,因此应该在方法终止时进行垃圾回收。

protected override void WndProc(ref Message m)
{
    base.WndProc(ref m); // I'm assuming the first trace can be caught here
    IntPtr hwnd = m.WParam;
    // Our hook tells us something got maximized
    if (Win32Import.UWM_MAXIMIZE == (UInt32)m.Msg)
    {
        // Figure out if we are temporarily disabled or using alternative profiles
        KeyStateInfo keyState = KeyboardInfo.GetKeyState(Settings.AlternativeProfileKey);
        Rectangle r = FindRectangle(MousePosition, (Settings.EnableAlternativeProfile && keyState.IsPressed ? AlternativeRegions : Regions));
        // Did we find a rectangle to place it in?
        if (r != Rectangle.Empty)
        {
            Rectangle position = Win32Import.GetWindowRectangle(hwnd);
            Rectangle previousPos = GetLocation(hwnd);
            if (position == r && previousPos != Rectangle.Empty)
            {
                // We are restoring the original position
                Win32Import.SetWindowPos(hwnd, IntPtr.Zero, previousPos.X, previousPos.Y, previousPos.Width, previousPos.Height, Win32Import.SWP_NOZORDER | Win32Import.SWP_NOSENDCHANGING);
            }
            else
            {
                // We are maximizing to a region
                Win32Import.ShowWindow(hwnd, Win32Import.WindowShowStyle.Restore);
                Win32Import.SetWindowPos(hwnd, IntPtr.Zero, r.X, r.Y, r.Width, r.Height, Win32Import.SWP_NOZORDER | Win32Import.SWP_NOSENDCHANGING);
                // Make sure we remember this location
                RememberLocation(hwnd, position);
            }
        }
    }
    else if (MaxTo64WindowHandleMessage == m.Msg)
    {
        // Store the window handle of our 64-bit subprocess
        SubProcess64WindowHandle = m.WParam;
    }
}

我无法重现该错误,即使运行该程序数天。

我的假设是系统的未碎片化内存或 GDI 句柄不足,但我无法在任何地方确认这一点。似乎没有关于此错误的任何好的文档。

还有什么想法吗?我可以做些什么来防止这个错误吗?

更新:由于缺乏一个体面的解决方案,这个问题被重新打开了更多的堆栈跟踪。简单地忽略它并不能解决问题。

【问题讨论】:

  • 与问题无关,但如何收集崩溃报告?
  • 在程序中使用 Fogbugz BugzScout(谷歌搜索)和自定义编写的全局错误处理程序。难度不大。
  • 出现错误时 Windows 应用程序事件日志中是否报告了任何内容?
  • 我不知道。我只知道这个错误是上面的堆栈跟踪。
  • 你想显示一个不透明的窗口吗?我的意思是,透明的?您的用户是否有旧显卡(不支持透明胶片和玻璃效果之类的东西?)。

标签: c# .net winapi win32exception


【解决方案1】:

泄漏或使用到许多 GDI 对象/句柄。这些可能会导致资源堆短缺。您可能无法重现,因为您的用户可能正在运行其他 GDI 资源繁重的程序或使用终端服务器,在这种情况下,他们必须与其他用户共享一些堆。见System Error. Code: 8. Not enough storage is available to process this command

Here您可以阅读有关桌面堆监视器工具的信息来诊断桌面堆问题。

Hereherehere 是 GDI 泄漏检测工具。

【讨论】:

  • 一定是这个。我假设此崩溃是由其他程序泄漏 GDI 句柄引起的。监控我的程序显示那里没有泄漏。
  • 你试过提升桌面堆吗?我的经验是,在用户之间共享部分桌面堆的终端服务器系统上,此错误更常发生。这或许可以解释为什么在这些情况下此错误更频繁地发生。
  • 问题是它从未在我的任何计算机上重现,所以我没有任何东西可以重现它。我正在向崩溃分析中添加更多数据收集,但需要很长时间才能获得更详细的数据。
  • @Lars:使用 GDIView,我已经确认 MaxTo 在运行时不会随着时间的推移增加“GDI Total”或“All GDI”。事实上,在后台运行时,它根本不会改变。打开它可以同时创建的所有窗口,“所有 GDI”计数几乎没有达到 200。
  • @Vagard:也许您可以要求用户增加他们的桌面堆,看看是否有帮助?还是请他们使用诊断工具并将结果发送给您?
【解决方案2】:

您的程序可能正在泄漏内核资源。开始使用 Taskmgr.exe 诊断此问题。查看 + 选择列,检查用户对象、GDI 对象和句柄计数。运行您的程序并观察这些是否稳定增加。一旦其中一个达到 10,000,您的程序就会死掉。

通过一种快速查看实际泄漏的方法,您可以开始注释代码以查看泄漏发生的位置。这可能与您的“钩子”有关。

【讨论】:

    【解决方案3】:

    问题可能不在于您的 WndProc - 您在调用堆栈中看到它的原因是因为 Windows 上与 GUI 相关的几乎所有内容都经过 WIN32 窗口过程。在您的控件中覆盖它只是为您提供一个挂钩点,以便在完成更高级别的 .NET 框架处理之前处理低级别的内容。

    这将是一个在黑暗中的完整镜头,但也许this post 可能是相关的? - 不过,可能不是那些堆栈跟踪。

    【讨论】:

    • 我看不到它的相关性,因为我看不到您链接到产生此错误的帖子。但是,MaxTo 主窗口确实有嵌套面板,只是深度没有达到 12 到 15 层,除非用户对他们的设置感到非常奇怪。 :)
    • @Vegard:如果是问题所在,堆栈跟踪可能看起来会有所不同。有什么方法可以让您获得完整的 Win32 堆栈跟踪,而不仅仅是 .net 跟踪?
    • 我不这么认为。我从来没有能够在我自己的机器上复制。堆栈跟踪只是来自 Exception 对象,我不知道如何获取 Win32 堆栈跟踪(并且在我弄清楚如何从 .NET 获取它之后必须为用户提供自定义构建)。
    【解决方案4】:

    我有许多具有自己资源的自定义 Windows 控件,因此当我创建许多控件时会出现此错误。解决这个问题 我在我的库中创建了资源文件,并在我的组件代码中使用了外部资源而不是资源。 之后我的异常消失了,已经用 3 倍以上的打开表单进行了测试,并且这个错误消失了。 所以看起来这是一个解决方案。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-08-30
      • 2010-10-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-06-23
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多