2010-08-25 67 views
9

我可以通過sbrk(0)獲取堆結束的地址,但是有沒有什麼方法可以通過編程方式獲取堆的開始地址,而不是通過解析/proc/self/maps的內容?如何以編程方式獲取Linux上堆的地址

+0

它讓我感到困惑......如果我得到一堆p =(int *)malloc(sizeof(int)); ,那麼爲什麼我不能通過p得到堆的開始地址? – bazysong 2016-03-30 06:23:04

回答

12

我認爲解析/proc/self/maps是Linux上查找堆段的唯一可靠方法。不要忘記,一些分配器(包括我的SLES中的一個)用於大塊mmap()因此內存不再是堆的一部分,並且可以位於任何隨機位置。

否則,通常ld會添加一個符號,該符號標記精靈中所有段的末尾,並且該符號被稱爲_end。例如: -

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

它的.bss結束,傳統的小精靈的最後一段相匹配。地址之後,有一些對齊,通常跟在堆之後。堆棧和mmap()(包括共享庫)位於地址空間的較高地址處。

我不確定它的可移植性如何,但顯然它在Solaris 10上的工作方式相同。在HP-UX 11上,映射看起來不同,並且堆似乎與數據段合併,但分配確實發生在_end。在AIX上,procmap根本不顯示堆/數據段,但分配也獲得超過_end符號的地址。所以現在看來​​目前相當便攜。

雖然,所有考慮,我不知道這是多麼有用。

P.S.測試程序:

#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

那麼,如果沒有辦法找到堆起始地址,malloc是如何實現的,它試圖將堆分成更小的內存塊? – Jun 2013-12-04 17:34:52

+0

請注意,在具有隨機偏移的系統中,這可能會失敗。它可以被啓用,但默認情況下,linux模糊堆的「開始」,因此很難從機器外部找到它(防止緩衝區溢出攻擊)。 – jwarner112 2015-03-22 23:32:22

+0

@Jun,libc調用'sbrk(0)'來查找堆的開始地址。但是這隻適用於libc:它在應用程序啓動期間,在main()之前被調用得非常早,因此堆的結束與堆的開始相同。在main()裏面,它不再是真的了。 – Dummy00001 2015-03-23 09:18:14

相關問題