.NET Out Of Memory Exception - используется 1,3 ГБ, но установлено 16 ГБ

91

Я получаю исключение нехватки памяти в моем приложении C #, когда использование памяти для приложения превышает 1,3 ГБ.

У меня была такая же проблема на 32-разрядной машине с 3 ГБ памяти, и тогда это имело смысл, но теперь я обновил оборудование до 64-разрядной машины с памятью 16 ГБ с высокопроизводительной материнской платой и оперативной памятью, но Out Of Memory исключение все еще происходит после 1,3 ГБ!

Я знаю, что нет отдельных объектов размером более 2 ГБ, а 1.3 в любом случае меньше 2 ГБ, поэтому встроенный предел MS 2 ГБ для одного объекта вряд ли будет проблемой ...

Похоже, что есть какой-то выключатель Windows, когда приложение достигает определенного порога использования памяти ... Тогда должен быть способ настроить это, возможно, в реестре?

Любая помощь будет оценена!

Paceman
источник
9
Ваша ОС тоже 64-битная?
fge 06
9
Даже если ваша ОС 64-битная, убедитесь, что ваш процесс также 64-
битный

Ответы:

90

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

Стоит упомянуть, что OutOfMemoryExceptionэто также может быть увеличено, если вы получаете 2GBпамять, выделенную одной коллекцией в CLR (скажем List<T>) как на архитектурах, так 32и на 64битах.

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

Тигран
источник
8
А что насчет AnyCPU?
dtb 06
1
Да, AnyCPU - это тоже вариант, где у вас есть возможность JIT-зависимого от архитектуры кода. Но ориентация на конкретную архитектуру по-прежнему может принести пользу в тех случаях, когда у вас нет (скажем) управляемых ресурсов. Я понятия не имею, что такое архитектура OP.
Тигран
4
Я знал это :) - Спасибо, Тигран, я пересобирал решение в x64 и исключение исчезло.
Paceman 06
63

Как уже упоминалось, компиляция приложения в x64 дает вам гораздо больше доступной памяти.

Но в случае, если нужно создать приложение на x86, есть способ поднять ограничение памяти с 1,2 ГБ до 4 ГБ (что является фактическим пределом для 32-битных процессов):

В папке VC / bin установочного каталога Visual Studio должен быть editbin.exeфайл. Итак, в моей установке по умолчанию я нахожу его в

C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\bin\editbin.exe

Для того, чтобы программа работала, возможно, вы должны vcvars32.batсначала выполнить ее в том же каталоге. Затем

editbin /LARGEADDRESSAWARE <your compiled exe file>

достаточно, чтобы ваша программа использовала 4 ГБ ОЗУ. <your compiled exe file>это exe, который VS сгенерировал при компиляции вашего проекта.

Если вы хотите автоматизировать это поведение каждый раз при компиляции проекта, используйте следующее событие Post-Build для выполняемого проекта:

if exist "$(DevEnvDir)..\tools\vsvars32.bat" (
   call "$(DevEnvDir)..\tools\vsvars32.bat"
   editbin /largeaddressaware "$(TargetPath)"
)

Примечание: то же самое можно сделать с помощью devenv.exeVisual Studio, чтобы также использовать 4 ГБ ОЗУ вместо 1,2 ГБ (но сначала сделайте резервную копию старого devenv.exe).

Дести
источник
Большое спасибо. У меня это работает. Но есть ли у нас какие-либо выявленные проблемы после увеличения лимита памяти до 4 ГБ?
Maverick
28

Стоит отметить, что по умолчанию для компиляции «Любой процессор» теперь установлен флажок «Предпочитать 32-битный». Если установлено AnyCPU, в 64-битной ОС с 16 ГБ ОЗУ все равно может возникнуть исключение нехватки памяти на 2 ГБ, если это отмечено.

Prefer32BitCheckBox

Тони
источник
2
Это полностью решило мои проблемы с
нехваткой
2

Похоже, у вас 64-битная арка, хорошо, но 32-битная версия среды выполнения .NET и / или 32-битная версия Windows.

Таким образом, адресное пространство, доступное для вашего процесса, остается прежним, оно не изменилось по сравнению с предыдущей настройкой.

Выполните обновление до 64-битной ОС и 64-битной версии .NET;)

fge
источник
1

Ваше приложение работает как 64- или 32-битный процесс? Вы можете проверить это в диспетчере задач.

Может быть, он работает как 32-битный, хотя вся система работает на 64-битном.

Если 32-битный, это может быть сторонняя библиотека. Но сначала убедитесь, что ваше приложение компилируется для «Any CPU», как указано в комментариях.

Жакко
источник
0

Если у вас 32-битная Windows, этот метод не работает без следующих настроек.

  1. Запустите командную строку cmd.exe (важно: запуск от имени администратора)
  2. введите bcdedit.exe и запустите
  3. Посмотрите на параметры "Increaseuserva", и там нет следующего утверждения.
  4. bcdedit / установить увеличениеuserva 3072
  5. и снова шаг 2 и проверьте параметры

Мы добавили эти настройки, и этот блок начался.

if exist "$(DevEnvDir)..\tools\vsvars32.bat" (
   call "$(DevEnvDir)..\tools\vsvars32.bat"
   editbin /largeaddressaware "$(TargetPath)"
)

Подробнее - команда increaseuserva: https://docs.microsoft.com/en-us/windows-hardware/drivers/devtest/bcdedit--set

Мехмет Курт
источник