¿Cuántos caracteres puede haber en una matriz de caracteres?

6 minutos de lectura

avatar de usuario
usuario666010

#define HUGE_NUMBER ???

char string[HUGE_NUMBER];
do_something_with_the_string(string);

Me preguntaba cuál sería el número máximo que podría agregar a una matriz de caracteres sin arriesgarme a posibles problemas de memoria, desbordamientos de búfer o similares. Quería obtener información del usuario, y posiblemente el máximo posible.

  • Depende en gran medida de la C que esté utilizando y de la plataforma en la que la esté compilando.

    – vbence

    18 de marzo de 2011 a las 12:27

Ver esta respuesta de Jack Klein (ver publicación original):

El estándar C original (ANSI 1989/ISO 1990) requería que un compilador tradujera con éxito al menos un programa que contuviera al menos un ejemplo de un conjunto de límites ambientales. Uno de esos límites era poder crear un objeto de al menos 32.767 bytes.

Este límite mínimo se elevó en la actualización de 1999 del estándar C a 65 535 bytes como mínimo.

No se requiere implementación de C para proporcionar objetos mayores que ese tamaño, lo que significa que no es necesario permitir una matriz de enteros mayor que (int)(65535 / sizeof(int)).

En términos muy prácticos, en las computadoras modernas, no es posible decir de antemano qué tan grande se puede crear una matriz. Puede depender de cosas como la cantidad de memoria física instalada en la computadora, la cantidad de memoria virtual proporcionada por el sistema operativo, la cantidad de otras tareas, controladores y programas que ya se están ejecutando y cuánta memoria está usando. Por lo tanto, su programa puede usar más o menos memoria ejecutándose hoy de lo que podría usar ayer o podrá usar mañana.

Muchas plataformas imponen sus límites más estrictos a los objetos automáticos, es decir, aquellos definidos dentro de una función sin el uso de la palabra clave ‘static’. En algunas plataformas, puede crear arreglos más grandes si son estáticos o mediante asignación dinámica.

Ahora, para proporcionar una respuesta un poco más personalizada, NO DECLARE MATRICES ENORMES PARA EVITAR DESBORDAMIENTOS DE BÚFER. Eso está cerca de la peor práctica que uno puede pensar en C. Más bien, dedique algún tiempo a escribir un buen código y asegúrese cuidadosamente de que no se produzca un desbordamiento del búfer. Además, si no conoce el tamaño de su matriz de antemano, mire mallocpodría ser útil 😛

depende de donde char string[HUGE_NUMBER]; es colocado.

  • ¿Está dentro de una función? Entonces la matriz estará en la pila, y si y Qué rápido su sistema operativo puede hacer crecer las pilas depende del sistema operativo. Así que aquí está la regla general: no coloque grandes arreglos en la pila.

  • Si está fuera de una función, entonces es global (memoria de proceso), si el sistema operativo no puede asignar tanta memoria cuando intenta cargar su programa, su programa fallará y su programa no tendrá oportunidad de notarlo (así que lo siguiente es mejor:)

  • Las matrices grandes deben ser malloced. Con malloc, el sistema operativo devolverá un puntero nulo si el malloc falló, según el sistema operativo y su esquema de paginación y esquema de asignación de memoria, esto fallará cuando 1) no haya una región continua de memoria libre lo suficientemente grande para la matriz o 2) el sistema operativo no pueda asignar suficientes regiones de memoria física libre a la memoria que aparece en su proceso como memoria continua.

Entonces, con arreglos grandes haz esto:

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

avatar de usuario
Juan Bode

Declarar matrices arbitrariamente grandes para evitar desbordamientos de búfer es una mala práctica. Si realmente no sabe de antemano qué tan grande debe ser un búfer, use malloc o realloc para asignar y ampliar dinámicamente el búfer según sea necesario, posiblemente utilizando un búfer de tamaño fijo más pequeño como intermediario.

Ejemplo:

#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");

       }
     }
   }

avatar de usuario
Jon

Si la matriz se va a asignar en la pila, entonces está limitado por el tamaño de la pila (normalmente 1 MB en Windows, algo de eso se usará para que tengas aún menos). De lo contrario, imagino que el límite sería bastante grande.

Sin embargo, hacer que la matriz sea realmente grande no es una solución para los problemas de desbordamiento del búfer. no lo hagas Use funciones que tengan un mecanismo para limitar la cantidad de búfer que usan para asegurarse de no sobrepasar su búfer y hacer que el tamaño sea algo más razonable (1K, por ejemplo).

Puedes usar malloc() para obtener porciones de memoria más grandes de lo que normalmente podría manejar una matriz.

avatar de usuario
jon hanna

Bueno, un desbordamiento de búfer no sería causado por un valor demasiado grande para NÚMERO_ENORME sino demasiado pequeño en comparación con lo que se escribió (escriba en el índice NÚMERO_ENORME o superior, y ha desbordado el búfer).

Aparte de eso, dependerá de la máquina. Ciertamente, hay sistemas que podrían manejar varios millones en el montón, y más o menos un millón en la pila (dependiendo de otras presiones), pero también hay algunos que no podrían manejar más de unos pocos cientos (los pequeños dispositivos integrados serían un ejemplo obvio). Si bien 65.535 es un mínimo especificado por el estándar, un dispositivo realmente pequeño podría especificar que el estándar se apartó deliberadamente por este motivo.

En términos reales, en una máquina grande, mucho antes de que realmente se quede sin memoria, está ejerciendo presión innecesariamente sobre la memoria de una manera que afectaría el rendimiento. Sería mejor dimensionar dinámicamente una matriz a un tamaño apropiado.

¿Ha sido útil esta solución?

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Configurar y más información
Privacidad