Сколько символов может быть в массиве символов? - PullRequest
19 голосов
/ 18 марта 2011
#define HUGE_NUMBER ???

char string[HUGE_NUMBER];
do_something_with_the_string(string);

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

Ответы [ 6 ]

14 голосов
/ 18 марта 2011

Смотрите этот ответ Джека Кляйна (см. оригинальный пост ):

Оригинальный стандарт C (ANSI 1989 / ISO 1990) требуется компилятор успешно перевести хотя бы один программа, содержащая хотя бы один пример набора экологических пределы. Одним из этих ограничений было возможность создать объект по крайней мере 32 767 байт.

Этот минимальный предел был повышен в Обновление 1999 года к стандарту C будет на минимум 65 535 байт.

Не требуется реализация C для обеспечить для объектов больше, чем это размер, что означает, что им не нужно чтобы разрешить массив больше чем (int) (65535 / sizeof (int)).

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

Многие платформы ставят свои самые строгие ограничения на автоматические объекты, то есть те, которые определены внутри функции без использования «статического» ключевое слово. На некоторых платформах вы можете создать большие массивы, если они статическое или динамическое распределение.

Теперь, чтобы дать немного более точный ответ, НЕ ОБЪЯВЛЯЙТЕ ОГРОМНЫЕ Массивы, чтобы избежать переполнения буфера . Это близко к худшей практике, о которой можно подумать в C. Скорее, потратьте некоторое время на написание хорошего кода и тщательно следите за тем, чтобы не происходило переполнение буфера. Также, если вы заранее не знаете размер вашего массива, посмотрите на malloc, это может пригодиться: P

7 голосов
/ 18 марта 2011

Зависит от того, где находится char string[HUGE_NUMBER];.

  • Это внутри функции? Тогда массив будет в стеке, и , если и , насколько быстро ваша ОС может наращивать стеки, зависит от ОС. Итак, вот общее правило: не помещайте огромные массивы в стек.

  • Является ли это функцией, то она глобальная (память процесса), если ОС не может выделить столько памяти при попытке загрузить вашу программу, ваша программа потерпит крах, и ваша программа не сможет заметить что (так лучше следующее:)

  • Большие массивы должны быть malloc 'ред. С помощью malloc ОС вернет нулевой указатель, если произошел сбой malloc, в зависимости от ОС, ее схемы пейджинга и схемы отображения памяти это может произойти сбой, если 1) нет достаточной большой области свободной памяти для массива или 2) ОС не может отобразить достаточно областей свободной физической памяти в память, которая представляется вашему процессу как непрерывная память.

Итак, с большими массивами сделайте это:

char* largeArray = malloc(HUGE_NUMBER);
if(!largeArray) { do error recovery and display msg to user }
4 голосов
/ 18 марта 2011

Объявление произвольно огромных массивов во избежание переполнения буфера - плохая практика.Если вы действительно заранее не знаете, какой должен быть размер буфера, используйте malloc или realloc для динамического выделения и расширения буфера по мере необходимости, возможно, используя в качестве посредника меньший буфер фиксированного размера.*

Пример:

#define PAGE_SIZE 1024  // 1K buffer; you can make this larger or smaller

/**
 * Read up to the next newline character from the specified stream.
 * Dynamically allocate and extend a buffer as necessary to hold
 * the line contents.
 *
 * The final size of the generated buffer is written to bufferSize.
 * 
 * Returns NULL if the buffer cannot be allocated or if extending it
 * fails.
 */
 char *getNextLine(FILE *stream, size_t *bufferSize)
 {
   char input[PAGE_SIZE];  // allocate 
   int done = 0;
   char *targetBuffer = NULL;
   *bufferSize = 0;

   while (!done)
   {
     if(fgets(input, sizeof input, stream) != NULL)
     {
       char *tmp;
       char *newline = strchr(input, '\n');
       if (newline != NULL)
       {
         done = 1;
         *newline = 0;
       }
       tmp = realloc(targetBuffer, sizeof *tmp * (*bufferSize + strlen(input)));
       if (tmp)
       {
         targetBuffer = tmp;
         *bufferSize += strlen(input);
         strcat(targetBuffer, input);
       }
       else
       {
         free(targetBuffer);
         targetBuffer = NULL;
         *bufferSize = 0;
         fprintf(stderr, "Unable to allocate or extend input buffer\n");

       }
     }
   }
3 голосов
/ 18 марта 2011

Если массив будет размещен в стеке, то вы ограничены размером стека ( обычно 1 МБ в Windows , часть его будет использоваться, поэтому у вас будет еще меньше).В противном случае я думаю, что предел будет довольно большим.

Однако , делающий массив действительно большим, не является решением проблем переполнения буфера .Не делай этого.Используйте функции, которые имеют механизм ограничения количества используемого буфера, чтобы убедиться, что вы не выходите за рамки буфера, и сделайте размер более разумным (например, 1 КБ).

1 голос
/ 18 марта 2011

Вы можете использовать malloc(), чтобы получить больший объем памяти, чем обычно может обрабатывать массив.

0 голосов
/ 18 марта 2011

Ну, переполнение буфера не было бы вызвано слишком большим значением для HUGE_NUMBER настолько, насколько оно слишком мало по сравнению с тем, что было записано в него (запись в индекс HUGE_NUMBER или выше, и вы переполнили буфер).

Кроме того, это будет зависеть от машины. Конечно, есть системы, которые могут обрабатывать несколько миллионов в куче и около миллиона в стеке (в зависимости от других нагрузок), но есть также и такие, которые не могут обрабатывать более нескольких сотен (небольшие встроенные устройства будут очевидный пример). В то время как 65 535 является стандартным минимумом, действительно небольшое устройство может указывать, что стандарт был преднамеренно отклонен по этой причине.

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

...