Asignación de memoria para variables globales y locales.

Aprendí que la memoria para las variables globales se asigna al inicio del progtwig, mientras que la memoria para las variables locales se asigna cada vez que se realiza una llamada a la función.

Caso 1:
He declarado una matriz de enteros global de tamaño 63500000 y la memoria utilizada es de 256 MB
Ideone Link

include  int a[63500000]; int main() { printf ("This code requires about 250 MB memory\n"); return 0; } 

Caso 2:
He declarado una matriz de enteros local del mismo tamaño en main () y la memoria utilizada es de 1.6 MB
Enlace de Ideone

 #include  int main() { int a[63500000]= {1,5,0}; printf ("This code requires only 1.6 MB \n"); //printf ("%d\n", a[0]); return 0; } 

Caso 3:
He declarado una matriz de enteros local del mismo tamaño en otra función y la memoria utilizada es de 1.6 MB
Ideone Link

 #include  void f() { int a[63500000]; } int main() { f(); return 0; } 

Por favor, explique por qué hay una diferencia en la memoria utilizada o mi concepto de asignación de memoria es incorrecto.

En primer lugar: el comstackdor de ideone es GCC.

Entonces, ¿qué hace GCC cuando comstacks esto ?:

 void foo () { int a[63500000]; } 

gcc -S -O2 foo.c genera:

 foo: pushl %ebp movl %esp, %ebp popl %ebp ret 

es decir, nada se asigna en la stack, en absoluto .

GCC simplemente optimiza la matriz porque nunca se usa.

GCC no hará esto con un global, porque es posible que se use un global en otra unidad de comstackción, por lo que no está seguro de que nunca se use. Además: el global no está en la stack (ya que es un global).

Ahora, veamos qué sucede cuando realmente usas la matriz local:

 int bar (int a, int b, int c) { int f[63500000]; f[a] = 9; f[b] = 7; return f[c]; } 

Las cosas son muy diferentes:

 bar: pushl %ebp movl %esp, %ebp subl $254000000, %esp movl 8(%ebp), %eax movl $9, -254000000(%ebp,%eax,4) movl 12(%ebp), %eax movl $7, -254000000(%ebp,%eax,4) movl 16(%ebp), %eax movl -254000000(%ebp,%eax,4), %eax leave ret 

Esta línea: subl $254000000, %esp corresponde al tamaño de la matriz. Es decir, la memoria está asignada en la stack.

Ahora, ¿qué pasa si trato de usar la función de bar en un progtwig?

 int bar (int a, int b, int c) { int f[63500000]; f[a] = 9; f[b] = 7; return f[c]; } int main (void) { return bar (0, 0, 0); } 

Ya vimos, que la función de bar asigna 250 o más megabytes en la stack. En mi instalación predeterminada de GNU / Linux, el tamaño de la stack está limitado a 8MB. Entonces, cuando el progtwig se ejecuta, provoca un “Fallo de segmentación”. Puedo boostlo si quiero, ejecutando lo siguiente en un shell:

 ulimit -s 1000000 #ie allow stack size to grow close to 1GB 

Entonces puedo ejecutar el progtwig, y ​​de hecho se ejecutará.

La razón por la que falla en el sitio web de ideone es que han limitado el tamaño de la stack al ejecutar progtwigs (y deberían, de lo contrario, los usuarios malintencionados podrían estropear su sistema).

Casos 2, 3

Las variables que define dentro de las funciones se asignan en la stack. Eso significa que la memoria asociada se limpia (la stack se “abre”) cuando se cierra la función.

Caso 1

Las variables definidas en el scope global se asignan en un segmento de datos (o, en general, un espacio de memoria solicitado al sistema operativo) que existe durante la vida útil del proceso.

Adicionalmente

La memoria asignada con malloc se asigna desde un montón y permanece asignada hasta que se libera explícitamente con free .

Tenga en cuenta que un sistema operativo moderno puede proporcionar el espacio de direcciones solicitado por un progtwig, pero no retroceder físicamente ese espacio de direcciones con RAM hasta que se acceda físicamente a la memoria (o una parte de la memoria a menudo llamada página ).

case 2 y el case 3 darían lugar a un desbordamiento de stack cuando solicite 64 MB de memoria de stack en la que su stack suele ser de 8 MB en Linux. Esto daría como resultado cosas malas aleatorias y / o volcados de núcleo y lockings.

esta respuesta explica en gran medida varias secciones del espacio de direcciones de proceso (.text, .bss, .data) y cómo se realizan las diferentes asignaciones de variables.