Obtener una excepción de desbordamiento de pila al declarar una matriz grande

6 minutos de lectura

avatar de usuario
patricio mcdonald

El siguiente código está generando un error de desbordamiento de pila para mí

int main(int argc, char* argv[])
{
    int sieve[2000000];
    return 0;
}

¿Cómo soluciono esto? Estoy usando Turbo C++ pero me gustaría mantener mi código en C

EDITAR:

Gracias por el consejo. El código anterior fue solo un ejemplo, en realidad declaro la matriz en una función y no en el subprincipal. Además, necesitaba que la matriz se inicializara en ceros, así que cuando busqué en Google malloc, descubrí que calloc era perfecto para mis propósitos.

Malloc/calloc también tiene la ventaja sobre la asignación en la pila de permitirme declarar el tamaño usando una variable.

  • Leí “excepción de desbordamiento de pila” y pensé “¿…? ¿Hay algún problema con el sitio?” Claramente paso demasiado tiempo aquí :-/

    – David Z.

    21 de febrero de 2009 a las 2:27

  • Estoy bastante seguro de que este tipo de pregunta debe haber surgido anteriormente en este sitio, pero buscar “desbordamiento de pila” no sirve de nada

    –Patricio McDonald

    21 de febrero de 2009 a las 2:33

  • Creo que todos los programadores de C terminan perdiendo mucho tiempo resolviendo este problema por primera vez.

    – MahlerFive

    21 de febrero de 2009 a las 3:20

  • Turbo C++ es una aplicación de 16 bits, lo que significa que utiliza la segmentación de la memoria, cada segmento tiene un tamaño de 64 KB, por lo que ninguna estructura puede ser más grande que este número, y el uso total de la memoria tiene un máximo de 640 KB (1 MB o más con algún administrador de memoria extendida). ). ¿Por qué necesita usar un compilador de más de 20 años?

    – phuclv

    28 de octubre de 2013 a las 3:33

  • A estas alturas, con suerte, ya habrás descubierto GCC. Entre otros lugares Viene incluido con el Código::Bloques IDE.

    – Ryyker

    21 de agosto de 2019 a las 12:11


avatar de usuario
arúl

Su matriz es demasiado grande para caber en la pila, considere usar el montón:

int *sieve = malloc(2000000 * sizeof(*sieve));

Si realmente quieres cambiar el tamaño de la pila, échale un vistazo a este documento.

Consejo: – No olvide liberar su memoria asignada dinámicamente cuando ya no la necesite.

  • Como esto es C, no necesita (y de hecho no debería) emitir el valor de retorno de malloc.

    – aib

    23 de febrero de 2009 a las 2:19

  • ¿Por qué no lanzarías el resultado de malloc? ¿No tendrías que lanzarlo desde el vacío* para poder hacer algo con él?

    usuario47589

    27 de febrero de 2009 a las 16:19

  • @ yodaj007: no es necesario que lo emita explícitamente. Dado que la variable asignada también es de tipo puntero, la asignación realiza una conversión implícita.

    – jweyrich

    10 de febrero de 2011 a las 17:45


  • @Amy Lea esto: “¿Lanzo el resultado de malloc?”. Explica varias razones por las que no lanzar malloc (o cualquiera de las otras funciones de asignación de memoria) en C.

    – WhozCraig

    26 de agosto de 2015 a las 17:11


  • Relacionado: Respuesta de preguntas y respuestas canónicas de C ++ que sugiere nuevo/eliminar o std::vector para el mismo problema: falla de segmentación en tamaños de matriz grandes

    – Peter Cordes

    5 de noviembre de 2021 a las 4:22

Hay 3 formas:

  1. Asignar matriz en el montón – usar malloc(), como sugirieron otros carteles. No olvides free() (aunque para main() no es tan importante: el sistema operativo limpiará la memoria al finalizar el programa).
  2. Declare la matriz a nivel de unidad: se asignará en el segmento de datos y será visible para todos (agregando static a la declaración limitará la visibilidad a la unidad).
  3. Declare su matriz como static – en este caso se asignará en el segmento de datos, pero visible solo en main().

  • Simplemente lo haría estático: main() solo debe llamarse una vez, para que no haya trampas; sin necesidad de malloc() aquí…

    – Cristóbal

    21 de febrero de 2009 a las 10:58

Sería mejor asignarlo en el montón, no en la pila. algo como

int main(int argc, char* argv[])
{
    int * sieve;
    sieve = malloc(20000);
    return 0;
}

  • Y verifique el tamiz para NULL

    – Paula

    12 mayo 2014 a las 12:26

  • “Solo soy un tamiz para ti” – El Zohan

    – Señor de los Dragones

    30 de julio de 2015 a las 19:19

  • creo que quisiste decir sieve = malloc(20000 * sizeof *sieve) – a menos que su plataforma tenga int de tamaño 1 (e incluso entonces, no incrustaría esa suposición en el código).

    –Toby Speight

    16 mayo 2018 a las 16:05

Eso es alrededor de 7 MB de espacio de pila. En Visual Studio, usaría /STACK:###,### para reflejar el tamaño que desea. Si realmente desea una pila enorme (podría ser una buena razón, usar LISP o algo así :), incluso la pila está limitada a asignaciones pequeñas antes de obligarlo a usar VirtualAlloc), también puede configurar su PE para construir con /LARGEADDRESSAAWARE (enlazador de Visual Studio nuevamente), pero esta configuración es su encabezado PE para permitir que su binario compilado aborde los 4 GB completos de espacio de direcciones de 32 bits (si se ejecuta en un WOW64). Si crea archivos binarios verdaderamente masivos, normalmente también necesitará configurar /bigobj como un parámetro de enlace adicional.

Y si aún necesita más espacio, puede violar radicalmente la convención usando algo similar a (nuevamente el enlace de MSVC) /merge:, que le permitirá empaquetar una sección en otra, para que pueda usar cada byte para un solo código compartido /sección de datos. Naturalmente, también necesitaría configurar los permisos de SECCIONES en un archivo def o con #pgrama.

Usa malloc. Todos verifican que el tipo de devolución no sea nulo, si es nulo, entonces su sistema simplemente no tiene suficiente memoria para adaptarse a tantos valores.

avatar de usuario
Iván Rubinson

Su matriz es enorme.

Es posible que su máquina o sistema operativo no tenga o quiera asignar tanta memoria.


Si necesita absolutamente una matriz enorme, puede intentar asignarla dinámicamente (usando malloc(...)), pero corre el riesgo de perder memoria. No olvides liberar la memoria.

La ventaja de malloc es que intenta asignar memoria en el montón en lugar de en la pila (por lo tanto, no obtendrá un desbordamiento de pila).

Puede verificar el valor que devuelve malloc para ver si la asignación tuvo éxito o falló. Si falla, simplemente intente malloc una matriz más pequeña.


Otra opción sería usar una estructura de datos diferente que se pueda cambiar de tamaño sobre la marcha (como una lista enlazada). Si esta opción es buena depende de lo que vaya a hacer con los datos.

Otra opción más sería almacenar cosas en un archivo, transmitiendo datos sobre la marcha. Este enfoque es el más lento.

Si opta por el almacenamiento en el disco duro, también podría usar una biblioteca existente (para bases de datos)

Como Turbo C/C++ es un compilador de 16 bits, el tipo de datos int consume alrededor de 2 bytes. 2 bytes*2000000=40,00,000 bytes=3,8147 MB ​​de espacio.

Las variables automáticas de una función se almacenan en la pila y causaron el desbordamiento de la memoria de la pila. En su lugar, utilice la memoria de datos [using static or global variable] o la memoria dinámica del montón [using the malloc/calloc] para crear la memoria necesaria según la disponibilidad de la asignación de memoria del procesador.

¿Ha sido útil esta solución?