Почему я получаю исключение из памяти в своем приложении C #?

Моя память 4G физическая, но почему я получил исключение из памяти, даже если я создаю только объект памяти 1.5G. Любые идеи почему? (Я видел в то же время на вкладке производительности диспетчера задач память не занята полностью, и я мог бы также вводить здесь – так что память на самом деле невелика, поэтому я думаю, что я ударил некоторые другие ограничения памяти)?

using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace TestBigMemoryv1 { class MemoryHolderFoo { static Random seed = new Random(); public Int32 holder1; public Int32 holder2; public Int64 holder3; public MemoryHolderFoo() { // prevent from optimized out holder1 = (Int32)seed.NextDouble(); holder2 = (Int32)seed.NextDouble(); holder3 = (Int64)seed.NextDouble(); } } class Program { static int MemoryThreshold = 1500; //M static void Main(string[] args) { int persize = 16; int number = MemoryThreshold * 1000 * 1000/ persize; MemoryHolderFoo[] pool = new MemoryHolderFoo[number]; for (int i = 0; i < number; i++) { pool[i] = new MemoryHolderFoo(); if (i % 10000 == 0) { Console.Write("."); } } return; } } } 

В обычном 32-битном приложении Windows процесс имеет только 2 ГБ адресной памяти. Это не имеет отношения к количеству доступной физической памяти.

Таким образом, 2 ГБ доступно, но 1,5 – это максимум, который вы можете выделить. Ключ в том, что ваш код не является единственным кодом, запущенным в этом процессе. Другой .5 ГБ, вероятно, CLR плюс fragmentация в этом процессе.

Обновление: в .Net 4.5 в 64-битном процессе вы можете иметь большие массивы, если включена опция gcAllowVeryLargeObjects :

На 64-битных платформах допускается использование массивов размером более 2 гигабайт (ГБ) в общем размере. Максимальное количество элементов в массиве – UInt32.MaxValue.

      

Просто дополнительный для других пунктов; если вы хотите получить доступ к грязному объему памяти, рассмотрите x64 – но имейте в виду, что максимальный размер одного объекта по-прежнему составляет 2 ГБ. И поскольку ссылки больше в x64, это означает, что вы фактически получаете меньший максимальный размер массива / списка для ссылочных типов. Конечно, к тому времени, когда вы нажмете этот предел, вы, вероятно, все испортите!

Другие варианты:

  • использовать файлы
  • использовать базу данных

(очевидно, что оба имеют разницу в производительности по сравнению с оперативной памятью)


Обновление: в версиях .NET до 4.5 максимальный размер объекта составляет 2 ГБ. Начиная с версии 4.5 вы можете выделять более крупные объекты, если включена функция gcAllowVeryLargeObjects . Обратите внимание, что ограничение на string не влияет, но «массивы» также должны покрывать «списки», поскольку списки поддерживаются массивами.

Просто добавьте к предыдущим ответам: вы можете выйти за пределы 2Gb для систем, загружаемых с флагами загрузки / 3Gb [и опционально userva].

Убедитесь, что вы создаете 64-битный процесс, а не 32-разрядный, который является стандартным методом компиляции Visual Studio. Для этого щелкните правой кнопкой мыши по вашему проекту, Свойства -> Сборка -> целевая платформа: x64. Как и любой 32-разрядный процесс, приложения Visual Studio, скомпилированные в 32-разрядной версии, имеют ограничение на виртуальную память 2 ГБ.

Каждый процесс имеет свою собственную виртуальную память, называемую адресным пространством, в которое он сопоставляет код, который он выполняет, и данные, которыми он управляет. 32-разрядный процесс использует 32-разрядные указатели адресов виртуальной памяти, что создает абсолютный верхний предел 4 ГБ (2 ^ 32) для объема виртуальной памяти, который может адресовать 32-битный процесс. Однако для работы операционной системы требуется половина (для ссылки на собственный код и данные), создавая ограничение в 2 ГБ для каждого процесса. Если ваше 32-разрядное приложение пытается потреблять более 2 ГБ адресного пространства, оно вернет «System.OutOfMemory», даже если физическая память вашего компьютера не заполнена.

64-разрядные процессы не имеют этого ограничения, так как используют 64-разрядные указатели, поэтому их теоретическое максимальное адресное пространство составляет 16 экзабайт (2 ^ 64). На самом деле Windows x64 ограничивает виртуальную память процессов до 8 ТБ. Тогда решение проблемы с памятью необходимо скомпилировать в 64-разрядной версии.

Однако размер объекта в Visual Studio по-прежнему ограничен 2 ГБ. Вы сможете создать несколько массивов, размер которых будет больше 2 ГБ, но по умолчанию вы не можете создавать массивы размером более 2 ГБ. Надеюсь, если вы все еще хотите создавать массивы размером более 2 ГБ, вы можете сделать это, добавив следующий код в файл app.config:

      

Как и другие плакаты, у вас есть адресная память с пропускной способностью 2 ГБ, как 32-битное приложение. Не забывайте о накладных расходах. Вы создаете массив из 93 миллионов объектов – если на один объект приходится 4 байта на один объект, это лишняя 350 МБ памяти.

Еще одна вещь, о которой нужно знать; некоторые объекты .NET требуют «непрерывной» памяти. т.е. если вы пытаетесь выделить большой массив, системе может понадобиться не только достаточная свободная память в вашем процессе, но также и для всей свободной памяти, которая будет в одном большом fragmentе … и, к сожалению, память процесса fragmentируется со временем, поэтому это может не будут доступны.

У некоторых объектов / типов данных есть это требование, а некоторые нет … Я не помню, какие из них выполняются, но я, кажется, помню, что StringBuilder и MemoryStream имеют разные требования.

В 32-битной операционной системе Windows максимальная «пользовательская» память, доступная для одного приложения, составляет 2 ГБ … при условии, что у вас в памяти 4 ГБ памяти.

Неуправляемое потребление памяти приложения VC ++ на сервере Windows

http://blogs.technet.com/markrussinovich/archive/2008/07/21/3092070.aspx

(Это забавно, что вы спросили об этом, потому что вчера я попросил почти то же самое …)

  • В чем разница между ссылкой __weak и __block?
  • Почему мне нужно называть super -dealloc последним, а не первым?
  • Как получить список файлов с определенным расширением в данной папке?
  • Как тег отличается от ветки в Git? Что я должен использовать здесь?
  • Найти физический адрес таблицы векторов исключений из модуля ядра
  • Процедура слишком большая
  • Как я могу найти элементы управления WPF по имени или типу?
  • Maven: Должен ли я хранить или удалять объявленные зависимости, которые также являются транзитными зависимостями?
  • Адрес памяти переменных в Java
  • Почему @autoreleasepool все еще нуждается в ARC?
  • Прочтите CSV из github в R
  • Давайте будем гением компьютера.