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
heapes, 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
heapcuando no está en el montón?060.Si está utilizando Windows, la razón es la estructura PE .
Su
heapvariable se almacena en la.datasecció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.datasecció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
.textsección es donde su código compilado es y.datacontiene suheapvariable. 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 deheapdesde 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
heapse coloca en0x8B0bytes después del inicio de la.datasección. Entonces, cada vez que ejecuto este código, mi dirección termina en0x8B0.fuente
heapcuando no está en el montón?El compilador pasó a colocar
heap0x60 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 lamainrutina. 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];defineheapcon 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 lasmallocimplementaciones 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