2010-08-25 24 views
9

Puedo obtener la dirección del final del montón con sbrk(0), pero ¿hay alguna forma de obtener mediante programación la dirección del inicio del montón, que no sea mediante el análisis del contenido de /proc/self/maps?Cómo obtener programáticamente la dirección del montón en Linux

+0

Me confunde ... si obtengo un montón con p = (int *) malloc (sizeof (int)); , entonces ¿por qué no puedo obtener la dirección de inicio del montón por p? – bazysong

Respuesta

12

Creo que el análisis /proc/self/maps es la única manera confiable en Linux para encontrar el segmento de montón. Y no olvide que algunos asignadores (incluido uno en mis SLES) sí lo utilizan para los bloques grandes mmap(), por lo que la memoria ya no forma parte del montón y puede estar en cualquier ubicación aleatoria.

De lo contrario, normalmente ld añade un símbolo que marca el final de todos los segmentos de duende y el símbolo se llama _end. Ej .:

extern void *_end; 
printf("%p\n", &_end); 

Coincide con el final de la .bss, tradicionalmente el último segmento del duende. Después de la dirección, con cierta alineación, normalmente sigue el montón. Stack (s) y mmap() s (incluidas las bibliotecas compartidas) están en las direcciones más altas del espacio de direcciones.

No estoy seguro de qué tan portátil es, pero aparentemente funciona de la misma manera en Solaris 10. En HP-UX 11 el mapa se ve diferente y el montón parece fusionarse con el segmento de datos, pero las asignaciones suceden después del _end. En AIX, procmap no muestra el segmento de montón/datos en absoluto, pero las asignaciones también obtienen las direcciones más allá del símbolo _end. Por lo tanto, parece ser en el momento bastante portátil.

Aunque, en conjunto, no estoy seguro de lo útil que es eso.

P.S. El programa de prueba:

#include <stdio.h> 
#include <stdlib.h> 

char *ppp1 = "hello world"; 
char ppp0[] = "hello world"; 
extern void *_end; /* any type would do, only its address is important */ 

int main() 
{ 
    void *p = calloc(10000,1); 
    printf("end:%p heap:%p rodata:%p data:%p\n", &_end, p, ppp1, ppp0); 
    sleep(10000); /* sleep to give chance to look at the process memory map */ 
    return 0; 
} 
+0

Bueno, si no hay forma de encontrar la dirección de inicio del montón, ¿cómo se implementa Malloc, que está tratando de dividir el montón en trozos de memoria más pequeños? – Jun

+0

Tenga en cuenta que esto puede fallar en un sistema con compensaciones aleatorias. Se puede habilitar, pero de forma predeterminada, Linux fuzzes donde el montón "comienza" por lo que es más difícil encontrarlo desde el exterior de la máquina (evitando los ataques de desbordamiento del búfer). – jwarner112

+0

@Jun, libc llama a 'sbrk (0)' para buscar la dirección del inicio del montón. Pero eso solo funciona para la libc: se llama muy temprano durante el inicio de la aplicación, antes de 'main()', y por lo tanto el final del montón es el mismo que el comienzo del montón. Dentro del 'main()' que ya no es verdadero. – Dummy00001

Cuestiones relacionadas