Вопрос

Наше приложение дает сбой на компьютере одного конкретного пользователя с 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, но не смог найти систематического обзора.

Это было полезно?

Решение 3

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

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

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

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

Другие советы

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

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

Также установите ПроцессЭксплорер на соответствующей машине.

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

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

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

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

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

DeleteDC(hdc);       //do it first (always before deleting objects)
DeleteObject(obj);
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top