Есть ли максимальный предел длины массива в С++?

Существует ли максимальная длина для массива в С++?

Является ли это лимит С++ или зависит от моей машины? Подходит ли он? Это зависит от типа, из которого сделан массив?

Могу ли я как-то нарушить этот предел или мне нужно искать лучший способ хранения информации? И какой должен быть самый простой способ?

Что мне нужно сделать, так это хранить long long int в массиве, я работаю в среде Linux. Мой вопрос: что мне делать, если мне нужно сохранить массив из N длинных длинных целых чисел с N > 10 цифрами?

Мне нужно это, потому что я пишу криптографический алгоритм (как, например, p-Pollard) для школы, и ударяю эту стенку из целых чисел и длины представления массивов.

Ответ 1

Есть два предела, оба не выполняются С++, а скорее аппаратными средствами.

Первый предел (никогда не должен быть достигнут) задается ограничениями типа размера, используемого для описания индекса в массиве (и его размера). Он задается максимальным значением, которое может принять система std::size_t. Этот тип данных всегда должен быть самым большим целым типом системы.

Другой предел - это ограничение физической памяти. Чем больше ваши объекты в массиве, тем скорее это ограничение достигается, потому что память заполнена. Например, vector<int> данного размера n обычно занимает примерно в четыре раза больше памяти, чем массив типа vector<char> (минус небольшое постоянное значение). Следовательно, a vector<char> может содержать больше элементов, чем vector<int>, прежде чем память будет заполнена. То же самое относится к родным массивам C-стиля int[] и char[].

Кроме того, на этот верхний предел может влиять тип allocator, используемый для построения vector, потому что allocator свободен для управления памятью любым способом, который он хочет. Очень странный, но бесчисленный мыслимый распределитель мог объединять память таким образом, чтобы идентичные экземпляры ресурса обменивались объектами. Таким образом, вы можете вставить много идентичных объектов в контейнер, который в противном случае использовал бы всю доступную память.

Кроме того, С++ не применяет никаких ограничений.

Ответ 2

Никто не упомянул ограничение на размер фрейма .

Можно выделить две ячейки памяти:

  • В куче (динамически распределенная память).
    Ограничение по размеру здесь представляет собой комбинацию доступного оборудования и способности ОС имитировать пространство с помощью других устройств для временного хранения неиспользуемых данных ( i.e. перемещать страницы на жесткий диск).
  • В стеке (локально объявленные переменные).
    Предел размера здесь определяется компилятором (с возможными ограничениями оборудования). Если вы читаете документацию компилятора, вы часто можете настроить этот размер.

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

int* a1 = new int[SIZE];  // SIZE limited only by OS/Hardware

В качестве альтернативы, если массив выделен в стеке, вы ограничены размером фрейма стека. N.B. векторы и другие контейнеры имеют небольшое присутствие в стеке, но обычно основная часть данных будет находиться в куче.

int a2[SIZE]; // SIZE limited by COMPILER to the size of the stack frame

Ответ 3

Рассматривая это с практической, а не теоретической точки зрения, в 32-битной системе Windows максимальный общий объем памяти, доступной для одного процесса, составляет 2 ГБ. Вы можете прервать ограничение, перейдя в 64-разрядную операционную систему с гораздо большей физической памятью, но нужно ли это делать или искать альтернативы, зависит от ваших предполагаемых пользователей и их бюджетов. Вы также можете расширить его, используя PAE.

Тип массива очень важен, поскольку выравнивание структуры по умолчанию для многих компиляторов составляет 8 байтов, что очень бесполезно, если проблема с памятью является проблемой. Если вы используете Visual С++ для работы с Windows, ознакомьтесь с директивой # pragma pack как способ преодоления этого.

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

Изменить: Учитывая немного больше информации о ваших точных требованиях, ваши потребности в хранении, по-видимому, находятся в диапазоне от 7,6 ГБ до 76 ГБ, что потребует довольно дорогого 64-битного окна для хранения в виде массива в памяти на С++. Возникает вопрос, почему вы хотите хранить данные в памяти, где вы предполагаете скорость доступа и разрешить произвольный доступ. Лучший способ хранить эти данные вне массива в значительной степени зависит от того, как вы хотите получить к нему доступ. Если вам необходимо получить доступ к элементам массива случайным образом, для большинства приложений обычно существуют способы группировки совокупностей данных, которые, как правило, получают доступ одновременно. Например, в больших ГИС и пространственных базах данных данные часто обрабатываются по географической области. В терминах программирования на С++ вы можете переопределить оператор массива [], чтобы при необходимости извлекать части данных из внешнего хранилища.

Ответ 4

Я согласен с вышесказанным, что если вы планируете свой массив с помощью

 int myArray[SIZE] 

то SIZE ограничено размером целого. Но вы всегда можете malloc кусок памяти и иметь указатель на нее, настолько большой, насколько вы хотите, пока malloc не возвращает NULL.

Ответ 5

Одна вещь, о которой я не думаю, упоминалась в предыдущих ответах.

Я всегда чувствую "плохой запах" в смысле рефакторинга, когда люди используют такие вещи в своем дизайне.

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

веселит,

Rob

Ответ 6

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

Ответ 7

Чтобы обобщить ответы, расширьте их и прямо ответьте на свой вопрос:

Нет, С++ не накладывает никаких ограничений на размеры массива.

Но поскольку массив должен храниться где-то в памяти, поэтому применяются ограничения, связанные с памятью, применяемые другими частями компьютерной системы. Обратите внимание, что эти ограничения напрямую не связаны с измерениями (= количество элементов) массива, а скорее его размером (= объем памяти). Размеры (D) и размер памяти ( S) не совпадают, поскольку они связаны памятью, взятой одним элементом ( E): S= D * E.

Теперь E зависит от:

  • тип элементов массива (элементы могут быть меньше или больше)
  • выравнивание памяти (для повышения производительности элементы размещаются по адресам, которые умножаются на некоторое значение, что вводит 'Пустое пространство (отступы) между элементами
  • размер статических частей объектов (в объектно-ориентированном программировании статические компоненты объектов одного и того же типа хранятся только один раз, независимо от количества таких объектов такого же типа)

Также обратите внимание, что вы обычно получаете разные ограничения, связанные с памятью, выделяя данные массива в стеке (как автоматическую переменную: int t[N]) или в кучу (динамическое распределение с помощью malloc()/new или используя механизмы STL ) или в статической части памяти процесса (как статическая переменная: static int t[N]). Даже при распределении на кучу вам по-прежнему нужен небольшой объем памяти в стеке, чтобы хранить ссылки на блоки памяти, выделенные кучей (но это обычно незначительно).

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

Источниками ограничений размера памяти являются

  • объем доступной для процесса памяти (которая ограничена 2 ^ 32 байтами для 32-битных приложений даже в 64-разрядных ядрах ОС),
  • разделение памяти процесса (например, объем памяти процесса, предназначенный для стека или кучи),
  • фрагментация физической памяти (многие рассеянные небольшие фрагменты свободной памяти не применимы для хранения одной монолитной структуры),
  • количество физической памяти,
  • и количество виртуальной памяти.

Их нельзя настроить на уровне приложений, но вы можете использовать другой компилятор (для изменения ограничений размера стека) или переносить приложение на 64-разрядные или переносить его на другую ОС или изменять физическая/виртуальная память (виртуальная? физическая?) машина.

Это не редкость (и даже целесообразно) рассматривать все вышеперечисленные факторы как внешние помехи и, следовательно, как возможные источники ошибок времени выполнения, а также тщательно проверять и реагировать на ошибки, связанные с распределением памяти, в вашем программном коде.

Итак, наконец: пока С++ не накладывает никаких ограничений, вам все равно придется проверять неблагоприятные условия, связанные с памятью, при запуске вашего кода...: -)

Ответ 8

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

Он использует двоичный поиск и на каждой итерации проверяет, возможен ли средний размер, создав код, который пытается создать массив размера. script пытается скомпилировать его (извините, эта часть работает только на Linux) и корректирует бинарный поиск в зависимости от успеха. Проверьте это:

import os

cpp_source = 'int a[{}]; int main() {{ return 0; }}'

def check_if_array_size_compiles(size):
        #  Write to file 1.cpp
        f = open(name='1.cpp', mode='w')
        f.write(cpp_source.format(m))
        f.close()
        #  Attempt to compile
        os.system('g++ 1.cpp 2> errors')
        #  Read the errors files
        errors = open('errors', 'r').read()
        #  Return if there is no errors
        return len(errors) == 0

#  Make a binary search. Try to create array with size m and
#  adjust the r and l border depending on wheather we succeeded
#  or not
l = 0
r = 10 ** 50
while r - l > 1:
        m = (r + l) // 2
        if check_if_array_size_compiles(m):
                l = m
        else:
                r = m

answer = l + check_if_array_size_compiles(r)
print '{} is the maximum avaliable length'.format(answer)

Вы можете сохранить его на свой компьютер и запустить его, и он напечатает максимальный размер, который вы можете создать. Для моей машины это 2305843009213693951.

Ответ 9

Как уже отмечалось, размер массива ограничен вашим оборудованием и вашей ОС (man ulimit). Однако ваше программное обеспечение может ограничиваться только вашим творчеством. Например, можете ли вы сохранить свой "массив" на диске? Вам действительно нужны долгие длительные попытки? Вам действительно нужен плотный массив? Вам вообще нужен массив?

Одним из простых решений было бы использовать 64-разрядный Linux. Даже если у вас физически недостаточно бара для вашего массива, ОС позволит вам выделять память так, как если бы вы делали, так как виртуальная память, доступная вашему процессу, вероятно, намного больше, чем физическая память. Если вам действительно нужно получить доступ ко всему в массиве, это означает сохранение его на диске. В зависимости от ваших шаблонов доступа могут быть более эффективные способы сделать это (т.е. Использовать mmap() или просто хранить данные последовательно в файле (в этом случае достаточно 32-битного Linux)).

Ответ 10

я обошел бы это, создав 2d динамический массив:

long long** a = new long long*[x];
for (unsigned i = 0; i < x; i++) a[i] = new long long[y];

подробнее об этом здесь fooobar.com/info/18366/...