Вопрос по memory-management, .net, c#, overflow – Почему «long» допускается как длина массива в C #?

15

Я хотел попытаться выделить массив из 4 миллиардов байтов, и это мой код C #:

long size = 4 * 1000;
size *= 1000;
size *= 1000;
byte[] array = new byte[size];

этот код не работает сSystem.OverflowException на строке, содержащейnew, Ладно получаетсяLength возвращаетсяintТаким образом, длина массива также ограничена тем, чтоint можно хранить.

Тогда почему нет ошибки времени компиляции иlong разрешено использовать как количество элементов массива при выделении?

Даже пейджинг имеет свои пределы. Предполагая 1024 МБ физической ОЗУ, Windows обычно ограничивает размер файла подкачки 1536 МБ. В совокупности вы сможете выделить 2560 МБ памяти. Поскольку окна устанавливают размер файла верхней страницы равным 1,5-кратному объему физической памяти, я скажу, что физическая память не может быть ограничивающим фактором, но он является фактором. konqi
@Joso: это 64-битный процесс, поэтому благодаря подкачке страниц он может выделять 3,7 места на диске. sharptooth
Таким образом, вы выделяете 3,7 ГБ памяти. Сколько оперативной памяти установлено на вашей машине? : D konqi
JoSo, (а) никто в здравом уме не будет использовать 64-битную Windows только на гигабайте памяти; (б) в наши дни память очень дешева, поэтому все, что меньше 8 ГиБ, в любом случае не имеет смысла; (в) вы читали ответы? Проблема в другом. Joey
Array.CreateInstance() дает более значимое сообщение об ошибке: «Массивы размером более 2 ГБ не поддерживаются». Bradley Smith

Ваш Ответ

5   ответов
10

Ответ: долго в .net означает Int64

И индексирование массива может быть Int64 согласно спецификации.

2-й вопрос: почему показывается переполнение?

Потому что ни одному объекту не может быть выделено более 2 ГБ памяти.

@ Миша: Это не нехватка памяти, просто один объект не может быть больше этого.
С такими претензиями (если они не очевидны, например,long быть псевдонимом дляSystem.Int64) всегда приятно подкреплять их ссылками.
Я не согласен с вашей второй точкой. Если его недостаточно, вы должны ожидать исключение OutOfMemoryException, а не OverflowException. Согласно спецификации исключение OverflowException следует вызывать только в том случае, если длина меньше нуля.
@Joey Возможно, вы правы, но я имею в виду объяснение OverflowException от mdkamruzzaman. В спецификации языка C # говорится, что OverflowException может быть выброшено, если любой спецификатор длины измерения меньше нуля. И это все, это единственная причина. Я не могу найти никакого упоминания в языковой спецификации до предела 2 ГБ. Здесь есть некоторое обсуждение:stackoverflow.com/questions/14889333/…
3

long является целочисленным типом, поэтому его можно использовать для определения массива; Исключением является построение слишком большого массива, а не использованиеlong.

Отлично, это работает просто отлично:

long size = 20;
byte[] array = new byte[size];
18

Поскольку спецификация говорит об этом в разделе 7.6.10.4:

Each expression in the expression list must be of type int, uint, long, or ulong, or implicitly convertible to one or more of these types.

Это скорее всего легкоallow создание массивов размером более 2 ГиБ, даже если они не поддерживаютсяyet (но будет безlanguage изменить, как только CLR сделает такое изменение).Mono поддерживает это, однако а также.NET 4.5, по-видимому, тоже позволит большие массивы.

Что касается длины массива, являющегосяint кстати: есть такжеLongLength, возвращаяlong, Это было в .NET 1.1 и, вероятно, изменение будущего.

+1 Хорошее место на 4.5 материале, надеюсь, Бог, я никогда не вижу, что включено в нашем приложении ...
В самом деле. Тогда вы могли бы сделать это многомерным массивом, чтобы обойти это. Но это тоже противно.
@ ErenErs & # xF6; nmez вы написали & quot; он говорит ... & quot; Где это сказано?
@Mishax: Во вторую ссылку я включил в свой ответ.
Похоже, что даже с изменением 4.5 рассматриваемый код все равно потерпит неудачу, потому что он говорит: «Максимальный индекс в любом одном измерении равен 2 147 483 591 (0x7FFFFFC7) для байтовых массивов и массивов однобайтовых структур и 2 146 435 071 (0X7FEFFFFF) для других». типы & Quot.
7

Это ограничение CLR, ни один объект не может превышать 2 ГБ, включая массивы:

Большой массив C # OutOfMemoryException

Это не зависит от 32-битных или 64-битных ОС. Тем не менее, это не мешает вам использовать больше, чем эта сумма в целом, только не на одном объекте.

Этоruntime ошибка, потому что если вы сохранитеlong (или другое значение инициализации) в пределах диапазона, это будет работать.

Вы можете инициализировать массивы со всеми целочисленными типами:sbyte, char, short, int, а такжеlong - все компилировать; неподписанные варианты тоже работают.

4

ссива.

<runtime>
    <gcAllowVeryLargeObjects enabled="true" />
</runtime>

https://msdn.microsoft.com/en-us/library/hh285054(v=vs.110).aspx

Похожие вопросы