Сколько символов может быть в массиве char?

#define HUGE_NUMBER ???

char string[HUGE_NUMBER];
do_something_with_the_string(string);

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

Ответ 1

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

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

Этот минимальный предел был поднят в 1999 обновление стандарта С, которое должно быть в не менее 65535 байт.

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

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

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

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

Ответ 2

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

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

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

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

Итак, с большими массивами выполните следующее:

char* largeArray = malloc(HUGE_NUMBER);
if(!largeArray) { do error recovery and display msg to user }

Ответ 3

Объявление произвольно огромных массивов, чтобы избежать переполнения буфера, является плохой практикой. Если вы действительно не знаете заранее, как большой буфер должен быть, используйте 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");

       }
     }
   }

Ответ 4

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

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

Ответ 5

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

Ответ 6

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

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

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