Я могу получить адрес конца кучи с помощью sbrk (0)
, но есть ли способ программно получить адрес начала кучи, кроме анализа содержимого / proc / self / maps
?
Я думаю, что синтаксический анализ /proc/self/maps
— единственный надежный способ найти сегмент кучи в Linux. И не забывайте, что некоторые распределители (включая один в моем SLES) используют для больших блоков mmap()
, поэтому память больше не является частью кучи и может находиться в любом случайном месте.
В противном случае обычно ld
добавляет символ, который отмечает конец всех сегментов в elf, и этот символ называется _end
. Например:
extern void *_end;
printf( "%p\n", &_end );
Соответствует концу .bss
, традиционно последнего сегмента эльфа. После адреса, с некоторым выравниванием, обычно следует куча. Стеки и mmap() (включая разделяемые библиотеки) находятся по старшим адресам адресного пространства.
Я не уверен, насколько он переносим, но, по-видимому, он работает так же на Solaris 10. В HP-UX 11 карта выглядит иначе, и куча кажется объединенной с сегментом данных, но выделение памяти происходит после _конец
. В 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;
}