Устранение неполадок ERROR_NOT_ENOUGH_MEMORY

Наше приложение не работает на компьютере конкретного пользователя с ERROR_NOT_ENOUGH_MEMORY ("Недостаточно памяти для обработки этой команды").

Эта ошибка, по-видимому, возникает где-то глубоко в рамках Delphi VCL, которую мы используем, поэтому я не уверен, какая функция Windows API ответственна.

Это проблема с памятью? Вызов GlobalMemoryStatus дает следующую информацию:

  • dwTotalPhys - 1063150000 (~ 1 ГБ)
  • dwAvailPhys - 26735000 (~ 27 МБ)
  • dwAvailPage - 1489000000 (~ 1,4 ГБ)

Мне кажется странным, что Windows позволяла бы настолько уменьшать доступную физическую память, когда в файле подкачки доступно так много места, но я не знаю достаточно об управлении виртуальной памятью Windows, чтобы знать, нормально это или нет. Это?

Если не память, то какой ресурс ограничен? Из того, что я читаю онлайн, ERROR_NOT_ENOUGH_MEMORY может быть результатом применения приложением любого из нескольких ограничений (объектов GDI, объектов USER, дескрипторов и т. д.) и необязательно памяти. Существует ли исчерпывающий список ограничений, которые накладывает Windows? Есть ли какой-нибудь способ узнать, какой предел нарушается? Я попробовал Google, но не смог найти систематического обзора.

4 ответа

Решение

Виновником в этом случае был CreateCompatibleBitmap. Очевидно, что Windows может применять довольно строгие системные ограничения на объем памяти, доступной для зависящих от устройства растровых изображений (см., Например, обсуждение в списке рассылки), даже если ваша система в противном случае имеет много памяти и много ресурсов GDI. (Эти общесистемные ограничения, очевидно, обусловлены тем, что Windows может выделять зависимые от устройства растровые изображения в памяти видеокарты.)

Решение состоит в том, чтобы просто использовать независимые от устройства растровые изображения (DIB) вместо этого (хотя они могут не обеспечивать столь же хорошую производительность). В этой статье базы знаний описывается, как выбрать оптимальный формат DIB для устройства.

Другие кандидаты на ограничение ресурсов (из ответов других и моих собственных исследований):

  • Ресурсы GDI (из этого ответа) - легко проверяются с помощью GDIView
  • Фрагментация виртуальной памяти (из этого ответа)
  • Настольная куча - смотрите здесь или здесь

Проверьте все возможности.

Проблемы GDI можно отслеживать с помощью бесплатной утилиты GDIView. Это единственный файл, который пользователи могут запустить без установщика.

Также установите ProcessExplorer на соответствующую машину.

Если у вас нет доступа к машине, попросите пользователя сделать скриншоты состояния, отслеживаемого приложениями. Очень похоже, это даст вам подсказку.

Более распространенной причиной этой ошибки, чем любая из перечисленных, является фрагментация пространства виртуальной памяти. Это ситуация, когда общий объем свободной памяти вполне достаточен, но свободное место фрагментировано, и в настоящее время выделяются различные биты пространства виртуальной памяти. Следовательно, вы можете получить ошибку нехватки памяти, когда запрос на память не может быть удовлетворен одним смежным блоком, несмотря на то, что он достаточно свободен.

Мой ответ может быть немного запоздалым, но, исходя из моего позднего опыта с той же проблемой, я делаю все тесты, иду за шагом, создаю DC, освобождаю его, использую DIBSection вместо CompatibleBitmap, используя утечки GDI/ инструменты памяти и т. д.

В конце концов (LOL) я обнаружил, что:

Я переключал приоритет этих двух звонков, тогда вся проблема была исправлена.

DeleteDC(hdc);       //do it first (always before deleting objects)
DeleteObject(obj);
Другие вопросы по тегам