2010-07-15 16 views
5

Duplicar posible:
C programming, why does this large array declaration produce a segmentation fault?C tamaño máximo en el principal

Esta es mi primera vez aquí, así que lo siento si me romper algunas reglas o si esto ha sido respondida antes. Recientemente he hecho un programa de C en el que tuve una matriz de

char buff[NR][1024*1024]; 

que necesitaba NR = 128. Por lo tanto el programa Alocate 128MB. Esto fue en main(). Lo intenté en algunos sistemas con suficiente memoria sin errores en la compilación. En el tiempo de ejecución, recibí una falla de segmentación en todos los sistemas. Funcionó para NR = 7, pero no para 8. Moví ese código fuera de main, lo que lo hizo global. No se bloqueó ni siquiera por 128. ¿Alguien sabe por qué sucedió esto? El compilador fue GCC

+0

Posible duplicado de la programación de [C, ¿por qué esta declaración de matriz grande produce una falla de segmentación?] (Http://stackoverflow.com/questions/3049934/c-programming-why-does-this-large-array-declaration -produce-a-segmentation-fault) –

Respuesta

16

El problema es que está desbordando la pila, que normalmente tiene unos pocos MB de tamaño (el tamaño exacto depende del sistema y de las opciones del compilador). Puede asignar la memoria en el montón utilizando en su lugar malloc.

+0

si usa C, probablemente debería usar malloc. –

+0

OP podría decirle al compilador que también use una pila más grande (http://stackoverflow.com/questions/156510/increase-stack-size-on-windows-gcc) .. pero esencialmente tienes razón :) – akira

+1

@SB : Sí, lo siento! Corregido ahora. @akira: No recomendaría aumentar el tamaño de la pila a 128MB. –

-4

El error de segmentación probablemente tenía otra razón. Utilice un depurador como gdb para determinar dónde ocurrió exactamente la falla de segmentación.

+1

-1: No, el programa casi definitivamente se bloqueó debido a esa línea. Ese código siempre resultará en bloqueos, generalmente con un error de desbordamiento de la pila o un error de segmentación, según el compilador. – Brian

+0

Fue solo por esa línea. Cuando lo comente, funcionaría normalmente. – Iustin

+0

Si lo ha comentado y funciona normalmente, ¿qué efecto exacto tuvo esto? – Puppy

5

Cuando lo pone en main() asigna los 128MB en la pila, y la pila suele ser limitada, con un límite que varía de un sistema a otro. Algunos podrían permitirle solo 8MB, otros tanto como usted pueda; su límite parece ser de 8MB, que es estándar para la mayoría de las plataformas Linux. Si se trata de un entorno de tipo POSIX, podría intentar controlar el límite con ulimit -s.

Cuando toma la declaración de main() y la convierte en estática, terminará en el segmento BSS (a menos que la inicialice), y estará restringida solo por el espacio del montón en la mayoría de los sistemas (que suele ser muy grande y/o ilimitado). Ver http://en.wikipedia.org/wiki/Data_segment

Sin embargo, si usted quiere que a nivel local y ad hoc, considerar la asignación de la NR megabytes mismo:

#define MB (1024*1024) 
char *bufp = malloc(NR*MB) 
char *buf[NR]; 
int i; 

for (i = 0; i < NR; i++) 
    buf[i] = bufp + i*MB; 

También puede asignar a cada trozo MB por separado, pero lo hice de esta manera en caso de que quiera toda el área es contigua en la memoria. Recuerde free(bufp) cuando haya terminado si está escribiendo una biblioteca de si su programa pasará a hacer otra cosa.

+0

+1 para calificar el comentario sobre 'free()' con "si está escribiendo una biblioteca o si su programa pasará a hacer otra cosa". –

+0

@R ..: fácil de complacer. :-) – integer

0

O puede aumentar el tamaño de asignación de pila para su programa. Por ejemplo, en VS 2008 vaya a Propiedades del proyecto -> Enlazador -> y configure Tamaño de confirmación de apilado.

+0

No estoy de acuerdo con esta idea (pero no te rechazaré). La pila no es una ubicación adecuada para grandes cantidades de datos. – tomlogic

1

Su matriz se asigna en la pila. La pila tiene un tamaño limitado (depende de la configuración del os y del enlazador). Creo que el tamaño de pila predeterminado es de aproximadamente 1 megabyte para win32 (compilador msvc) y 8 megabytes para linux (gcc). Cualquier cantidad mayor que eso provocará el desbordamiento de la pila, lo que causará segfault instantáneo.

soluciones posibles: tamaño de la pila

  1. aumento en las configuraciones de enlace.
  2. Asignar memoria dinámicamente (utilizando malloc).
  3. Make array global.
  4. Hacer una matriz estática.

Hacer variable global/estática causará (en los compiladores que he visto, al menos) que se asigne fuera de la pila, ya sea en datos o en segmentos de código, lo que no afectará al tamaño de la pila.

0

Puede usar malloc, a menudo también puede declararlo fuera de main utilizando el alcance del archivo. Si lo necesita en otro archivo c, mire en usar extern. Este método no se recomienda a menos que tenga una buena razón para tener una variable de ámbito de archivo (la nota c no tiene realmente variables "globales", solo las del alcance del archivo a las que se puede acceder con extern). Google es tu amigo en estas técnicas también :). También puede encontrar la configuración para el tamaño de pila máximo que acompaña a su compilador/sistema operativo. Busque "establecer tamaño de pila". De nuevo, no recomendado, aprenda a usar malloc :).

Cuestiones relacionadas