如何以编程方式获取Linux上的堆地址

jch*_*chl 9 c linux heap

我可以获取堆结尾的地址sbrk(0),但有没有办法以编程方式获取堆的起始地址,而不是通过解析内容/proc/self/maps

Dum*_*001 12

我认为解析/proc/self/maps是Linux上唯一可靠的方法来查找堆段.并且不要忘记一些分配器(包括我的SLES中的一个)确实用于大块,mmap()因此内存不再是堆的一部分,并且可以在任何随机位置.

否则,通常ld会在elf中添加一个标记所有段末尾的符号,并调用该符号_end.例如:

extern void *_end;
printf( "%p\n", &_end );
Run Code Online (Sandbox Code Playgroud)

它匹配.bss传统上最后一段精灵的结尾.在地址之后,通过一些对齐,通常在堆之后.Stack(s)和mmap()s(包括共享库)位于地址空间的较高地址.

我不确定它是多么可移植,但显然它在Solaris 10上的工作方式相同.在HP-UX 11上,映射看起来不同,堆似乎与数据段合并,但分配确实发生在_end.在AIX上,procmap根本不显示堆/数据段,但分配也会通过_end符号获取地址.所以它似乎目前非常便携.

虽然,所有人都考虑过,但我不确定它有多大用处.

PS测试程序:

#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;
}
Run Code Online (Sandbox Code Playgroud)

  • 那么,如果无法找到堆起始地址,那么 malloc 是如何实现的,它试图将堆分割成更小的内存块? (2认同)