Win32Exception Недостаточно памяти для обработки этой команды - PullRequest
12 голосов
/ 14 февраля 2009

Благодаря моей автоматической коллекции аварий для 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, но я нигде не могу это подтвердить. Похоже, нет хорошей документации по этой ошибке.

Есть идеи, что еще это может быть? Могу ли я сделать что-нибудь, чтобы предотвратить эту ошибку?

Обновление : вопрос был вновь открыт с большим количеством следов стека из-за отсутствия достойного решения. Простое игнорирование не решает проблему.

Ответы [ 4 ]

12 голосов
/ 14 февраля 2009

Утечка или использование многих объектов / дескрипторов GDI. Это может привести к нехватке ресурсов. Возможно, вы не сможете воспроизвести, потому что у ваших пользователей могут быть запущены другие ресурсоемкие программы с GDI-ресурсами или они используют Terminal Server, и в этом случае им приходится делить часть кучи с другими пользователями. См. Системная ошибка. Код: 8. Недостаточно памяти для обработки этой команды

Здесь вы можете прочитать об инструменте Desktop Heap Monitor для диагностики проблем кучи рабочего стола.

Здесь и здесь и здесь - инструменты обнаружения утечки GDI.

5 голосов
/ 14 февраля 2009

Ваша программа, вероятно, пропускает ресурсы ядра. Начните диагностировать эту проблему с помощью Taskmgr.exe. Просмотр + Выбор столбцов, проверка объектов пользователя, объектов GDI и счетчика дескрипторов. Запустите вашу программу и наблюдайте, если какой-либо из них неуклонно растет. Как только один из них достигнет 10000, ваша программа умрет.

Имея способ быстро увидеть утечку в действии, вы можете начать комментировать код, чтобы увидеть, где происходит утечка. Вероятно, это как-то связано с вашим "крючком".

1 голос
/ 21 сентября 2010

Возможно, проблема не в вашем WndProc - причина, по которой вы видите его в стеках вызовов, заключается в том, что почти все, что связано с GUI в Windows, проходит через оконную процедуру WIN32. Переопределение его в вашем элементе управления просто дает вам ловушку для обработки низкоуровневых вещей перед выполнением высокоуровневой обработки .NET Framework.

Это будет полный выстрел в темноте, но, возможно, этот пост может быть актуален? - вероятно, не с этими следами стека, однако.

0 голосов
/ 16 июля 2013

У меня было много пользовательских элементов управления Windows с собственными ресурсами, поэтому при создании многих элементов управления появляется эта ошибка. Чтобы исправить эту проблему Я сделал Resource файл в моей библиотеке и использовал внешние ресурсы вместо ресурсов в коде моего компонента. После этого мое исключение прошло, уже проверено с 3 раза больше открытых форм и эта ошибка исчезла. Похоже, это решение.

...