2010-08-25 10 views
9

Ich kann die Adresse des Endes des Heap mit sbrk(0) erhalten, aber gibt es eine Möglichkeit, programmgesteuert die Adresse des Beginns des Heap zu erhalten, außer durch das Parsen der Inhalt von /proc/self/maps?Wie programmgesteuert die Adresse des Heap unter Linux

+0

Es macht mich verwirrt ... wenn ich einen Haufen mit p = (int *) malloc (sizeof (int)); , warum kann ich dann die Startadresse des Heapspeichers nicht p abrufen? – bazysong

Antwort

12

Ich glaube, Parsing /proc/self/maps ist die einzige zuverlässige Möglichkeit auf dem Linux, das Heap-Segment zu finden. Und vergessen Sie nicht, dass einige Zuweiser (einschließlich einer in meinem SLES) für große Blöcke mmap() verwenden, so dass der Speicher nicht mehr Teil des Heaps ist und an jedem zufälligen Ort sein kann.

Sonst fügt ld normalerweise ein Symbol hinzu, das das Ende aller Segmente in elf kennzeichnet, und das Symbol heißt _end. Z.B .:

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

Es stimmt mit dem Ende des .bss, traditionell das letzte Segment der Elf. Nach der Adresse folgt normalerweise mit einiger Ausrichtung der Heap. Stack (s) und mmap() s (einschließlich der gemeinsam genutzten Bibliotheken) befinden sich an den höheren Adressen des Adressraums.

Ich bin mir nicht sicher, wie tragbar es ist, aber anscheinend funktioniert es genauso auf Solaris 10. Unter HP-UX 11 sieht die Karte anders aus und der Heap scheint mit dem Datensegment zusammengeführt zu werden _end. Unter AIX zeigt procmap kein Heap/Datensegment, aber auch Zuweisungen erhalten die Adressen nach dem _end Symbol. So scheint es im Moment ziemlich tragbar zu sein.

Obwohl alle in Betracht gezogen, ich bin mir nicht sicher, wie nützlich das ist.

P.S. Das Testprogramm:

#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

Nun, wenn keine Möglichkeit gefunden wird, die Startadresse des Heaps zu finden, wie wird malloc implementiert, das versucht, den Heap in kleinere Speicherblöcke aufzuteilen? – Jun

+0

Beachten Sie, dass dies in einem System mit randomisierten Offsets fehlschlagen kann. Es kann aktiviert werden, aber linux fuzzes standardmäßig, wo der Heap "startet", so dass es schwieriger ist, es von außerhalb des Rechners zu finden (verhindert Pufferüberlauf-Angriffe). – jwarner112

+0

@Jun, libc ruft 'sbrk (0)' auf, um die Adresse des Beginns des Heaps zu finden. Aber das funktioniert nur für die libc: Es wird sehr früh beim Start der Anwendung aufgerufen, vor dem 'main()', und somit ist das Ende des Heapspeichers gleich dem Anfang des Heapspeichers. Innerhalb der 'main()' ist es nicht mehr wahr. – Dummy00001

Verwandte Themen