Tengo un programa de CA que se ve así
C Principal
#include <stdio.h>
#define SOME_VAR 10
static int heap[SOME_VAR];
int main(void) {
printf("%p", heap);
return 0;
}
y genera esto cuando ejecuto el programa compilado varias veces
0x58aa7c49060
0x56555644060
0x2f8d1f8e060
0x92f58280060
0x59551c53060
0xd474ed6e060
0x767c4561060
0xf515aeda060
0xbe62367e060
¿Por qué siempre termina en 060? ¿Y la matriz está almacenada en el montón?
Editar: estoy en Linux y tengo ASLR. Compilé el programa usando gcc
Respuestas:
Las direcciones difieren debido a ASLR (ramdomización del diseño del espacio de direcciones). Con esto, el binario se puede mapear en diferentes ubicaciones en el espacio de direcciones virtuales.
La variable
heap
es, en contraste con su nombre, no se encuentra en el montón, sino en elbss
. El desplazamiento en el espacio de direcciones es, por lo tanto, constante.Las páginas se asignan a la granularidad de la página, que es 4096 bytes (hexadecimal: 0x1000) en muchas plataformas. Esta es la razón por la cual los últimos tres dígitos hexadecimales de la dirección son los mismos.
Cuando hizo lo mismo con una variable de pila , la dirección podría incluso variar en los últimos dígitos en algunas plataformas (es decir, Linux con núcleos recientes), porque la pila no solo está asignada en otro lugar sino que también recibe un desplazamiento aleatorio al inicio.
fuente
heap
cuando no está en el montón?060
.Si está utilizando Windows, la razón es la estructura PE .
Su
heap
variable se almacena en la.data
sección del archivo y su dirección se calcula en función del inicio de esta sección. Cada sección se carga en una dirección de forma independiente, pero su dirección inicial es múltiple del tamaño de la página. Debido a que no tiene otras variables, es probable que su dirección sea el inicio de la.data
sección, por lo que su dirección será múltiplo del tamaño del fragmento.Por ejemplo, esta es la tabla de la versión compilada de Windows de su código: La
.text
sección es donde su código compilado es y.data
contiene suheap
variable. Cuando su PE se carga en la memoria, las secciones se cargan en una dirección diferente y la devuelveVirtualAlloc()
y será múltiplo del tamaño de la página. Pero la dirección de cada variable es relativa al inicio de la sección que ahora es un tamaño de página. Por lo tanto, siempre verá un número fijo en los dígitos más bajos. Dado que la dirección relativa deheap
desde el inicio de la sección se basa en el compilador, las opciones de compilación, etc., verá un número diferente del mismo código, pero diferentes compiladores, pero cada vez que se imprima se corrige.Cuando compilo código, noté que
heap
se coloca en0x8B0
bytes después del inicio de la.data
sección. Entonces, cada vez que ejecuto este código, mi dirección termina en0x8B0
.fuente
heap
cuando no está en el montón?El compilador pasó a colocar
heap
0x60 bytes en un segmento de datos que tiene, posiblemente porque el compilador tiene otras cosas en los primeros 0x60 bytes, como los datos utilizados por el código que inicia lamain
rutina. Por eso ves "060"; es justo donde estaba, y no tiene gran importancia.La aleatorización del diseño del espacio de direcciones cambia las direcciones base utilizadas para varias partes de la memoria del programa, pero siempre lo hace en unidades de 0x1000 bytes (porque esto evita causar problemas con la alineación y otros problemas). Entonces verá que las direcciones fluctúan por múltiplos de 0x1000, pero los últimos tres dígitos no cambian.
La definición
static int heap[SOME_VAR];
defineheap
con la duración del almacenamiento estático. Las implementaciones típicas de C lo almacenan en una sección de datos generales, no en el montón. El "montón" es un nombre inapropiado para la memoria que se utiliza para la asignación dinámica. (Es un nombre inapropiado porque lasmalloc
implementaciones pueden usar una variedad de estructuras de datos y algoritmos, no limitados a montones. Incluso pueden usar múltiples métodos en una implementación).fuente