2014-01-28 4 views
0

Когда sbrk() возвращает указатель на адрес, который является началом кучи, являются ли адреса восходящими или нисходящими? Например, если бы у меня была куча в 10 байт с адресов от 1 до 10, будет ли sbrk() возвращать указатель на адрес 10 или 1?C: sbrk() по возрастанию или по убыванию?

На подобной заметке адреса кучи имеют тенденцию расти «вниз» ... но как я могу выяснить, увеличивается или уменьшается количество адресов на моем компьютере?

+1

Что о вызове sbrk() дважды и тестирование ли увеличение или уменьшение адреса? – Jens

ответ

2

страница на Mac OS X говорит:

В brk и sbrk функции исторические раритеты, оставшиеся от предыдущих дней до появления управления виртуальной памятью.

Текущее значение разрыва программы надежно возвращается sbrk(0).

Функция возвращает sbrk функция возвращает указатель на базу новое хранилище в случае успеха; в противном случае -1 с errno, чтобы указать, почему не удалось выполнить распределение.

Предположим, вы используете:

void *base = sbrk(1024); 

После этого, при условии отсутствия ошибки, base будет содержать начальный адрес 1024 байт (минимум) блока памяти; (char *)base + 1024 будет зависеть от того, что вы запросили, хотя он все равно может быть действительным, так как размер страницы может быть больше 1024.

Он не говорит прямо, будет ли последующее распределение иметь больший или меньший адрес, чем другой. Однако он, вероятно, будет в порядке возрастания адресов.

brk() функция устанавливает перерыв или наименьший адрес сегмента данных процесса (неинициализированные данные) в адр (непосредственно над СБС). Адресация данных ограничена между addr и наименьшим указателем стека к сегменту стека. Память выделяется brk в размерах страниц; если addr не равномерно делится на размер системной страницы, то будет увеличен до границы следующей страницы.

Это означает, что дополнительное пространство находится после сегментов данных и bss и растет к стеку (который растет вниз в памяти). Однако, полагаясь на это, вероятно, будет безрассудно. Лучше всего использовать sbrk(0), чтобы установить текущий конец после вызова sbrk(extra), чтобы получить дополнительное пространство; это скажет вам, что вы действительно получили, и два адреса говорят вам, где они были доступны.

+0

Для меня часть «исторических любопытств» - это огромное неуверенность, возложенная на сотрудника Apple «Я чувствую себя превосходным», который, возможно, думал, что они действительно работают и имеют новые способы делать вещи, тогда как мир Unix был заморожен и еще один старый джайзер в сравнении. Тем не менее, он просто сделал себя дураком, а теперь история - это остатки этой фразы в руководстве Apple, которая служит только его (и яблочной) дискредитации из-за необоснованного высокомерия. Теперь я хотел бы получить объяснение этой фразы. –

+0

позже примечание: кажется, эта фраза на самом деле происходит из оригинального руководства BSD. поэтому сыпь относится к некоторым BSD «я чувствую себя превосходным» парнем, а не к Apple. Парень из Apple только исказил эту фразу, чтобы сделать ее еще более высокомерной, lol. –

0

Если вы находитесь в Linux, вы можете изучить /proc/$PID/maps, чтобы узнать, как виртуальное адресное пространство используется для каждого процесса.

Пример кода: mappingTest.c

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

int foo(int depth) { 
    char buf[8192]; 
    if (0 == depth) 
     printf("%p\n", buf); 
    if (1000 < depth) { 
     printf("%p\n", buf); 
     return getchar(); 
    } else { 
     return 1 + foo(depth + 1); 
    } 
} 

int main() { 
    const size_t SIZE = 1000 * 1000 * 1000; 
    getchar(); 
    char * const p = malloc(SIZE); 
    printf("%p\n", p); 
    getchar(); 
    free(p); 
    getchar(); 
    foo(0); 
    return 0; 
} 

Примечание: char buf[8192] и рекурсия 1000 раз предположим, что максимальный размер стека составляет 8 МБ (вы можете подтвердить с ulimit -s.)

$ gcc mappingTest.c -o mappingTest -Wall -Wextra -Wno-missing-field-initializers -std=c89 -O0 -g3 && echo OK 
OK 
$ ./mappingTest 

На 1-м getchar(), мы видим следующие отображения памяти для процесса:

$ cat /proc/`pidof mappingTest`/maps 
00400000-00401000 r-xp 00000000 08:05 21687266       /home/nodakai/prog/exp/mappingTest 
00600000-00601000 r--p 00000000 08:05 21687266       /home/nodakai/prog/exp/mappingTest 
00601000-00602000 rw-p 00001000 08:05 21687266       /home/nodakai/prog/exp/mappingTest 
7f2e96e8a000-7f2e9703f000 r-xp 00000000 08:05 14314431     /lib/x86_64-linux-gnu/libc-2.15.so 
7f2e9703f000-7f2e9723f000 ---p 001b5000 08:05 14314431     /lib/x86_64-linux-gnu/libc-2.15.so 
7f2e9723f000-7f2e97243000 r--p 001b5000 08:05 14314431     /lib/x86_64-linux-gnu/libc-2.15.so 
7f2e97243000-7f2e97245000 rw-p 001b9000 08:05 14314431     /lib/x86_64-linux-gnu/libc-2.15.so 
7f2e97245000-7f2e9724a000 rw-p 00000000 00:00 0 
7f2e9724a000-7f2e9726c000 r-xp 00000000 08:05 14314443     /lib/x86_64-linux-gnu/ld-2.15.so 
7f2e97443000-7f2e97446000 rw-p 00000000 00:00 0 
7f2e97469000-7f2e9746c000 rw-p 00000000 00:00 0 
7f2e9746c000-7f2e9746d000 r--p 00022000 08:05 14314443     /lib/x86_64-linux-gnu/ld-2.15.so 
7f2e9746d000-7f2e9746f000 rw-p 00023000 08:05 14314443     /lib/x86_64-linux-gnu/ld-2.15.so 
7fffa6d43000-7fffa6d64000 rw-p 00000000 00:00 0       [stack] 
7fffa6dff000-7fffa6e00000 r-xp 00000000 00:00 0       [vdso] 
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0     [vsyscall] 

Мы хит Enter и перейти ко 2-му getchar().

Я получил 0x7f2e5b4dd010 на моем терминале в качестве значения p и он попадет в первую анонимное отображение области 7f2e5b4dd000-7f2e96e8a000 в листинге ниже, но didin't существует в приведенном выше списке.

$ cat /proc/`pidof mappingTest`/maps 
00400000-00401000 r-xp 00000000 08:05 21687266       /home/nodakai/prog/exp/mappingTest 
00600000-00601000 r--p 00000000 08:05 21687266       /home/nodakai/prog/exp/mappingTest 
00601000-00602000 rw-p 00001000 08:05 21687266       /home/nodakai/prog/exp/mappingTest 
7f2e5b4dd000-7f2e96e8a000 rw-p 00000000 00:00 0 
7f2e96e8a000-7f2e9703f000 r-xp 00000000 08:05 14314431     /lib/x86_64-linux-gnu/libc-2.15.so 
7f2e9703f000-7f2e9723f000 ---p 001b5000 08:05 14314431     /lib/x86_64-linux-gnu/libc-2.15.so 
7f2e9723f000-7f2e97243000 r--p 001b5000 08:05 14314431     /lib/x86_64-linux-gnu/libc-2.15.so 
7f2e97243000-7f2e97245000 rw-p 001b9000 08:05 14314431     /lib/x86_64-linux-gnu/libc-2.15.so 
7f2e97245000-7f2e9724a000 rw-p 00000000 00:00 0 
7f2e9724a000-7f2e9726c000 r-xp 00000000 08:05 14314443     /lib/x86_64-linux-gnu/ld-2.15.so 
7f2e97443000-7f2e97446000 rw-p 00000000 00:00 0 
7f2e97468000-7f2e9746c000 rw-p 00000000 00:00 0 
7f2e9746c000-7f2e9746d000 r--p 00022000 08:05 14314443     /lib/x86_64-linux-gnu/ld-2.15.so 
7f2e9746d000-7f2e9746f000 rw-p 00023000 08:05 14314443     /lib/x86_64-linux-gnu/ld-2.15.so 
7fffa6d43000-7fffa6d64000 rw-p 00000000 00:00 0       [stack] 
7fffa6dff000-7fffa6e00000 r-xp 00000000 00:00 0       [vdso] 
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0     [vsyscall] 

Мы нажимаем Enter и переходим к третьему getchar().

В приведенном ниже списке мы видим, что анонимная область отображения исчезла из-за free().

$ cat /proc/`pidof mappingTest`/maps 
00400000-00401000 r-xp 00000000 08:05 21687266       /home/nodakai/prog/exp/mappingTest 
00600000-00601000 r--p 00000000 08:05 21687266       /home/nodakai/prog/exp/mappingTest 
00601000-00602000 rw-p 00001000 08:05 21687266       /home/nodakai/prog/exp/mappingTest 
7f2e96e8a000-7f2e9703f000 r-xp 00000000 08:05 14314431     /lib/x86_64-linux-gnu/libc-2.15.so 
7f2e9703f000-7f2e9723f000 ---p 001b5000 08:05 14314431     /lib/x86_64-linux-gnu/libc-2.15.so 
7f2e9723f000-7f2e97243000 r--p 001b5000 08:05 14314431     /lib/x86_64-linux-gnu/libc-2.15.so 
7f2e97243000-7f2e97245000 rw-p 001b9000 08:05 14314431     /lib/x86_64-linux-gnu/libc-2.15.so 
7f2e97245000-7f2e9724a000 rw-p 00000000 00:00 0 
7f2e9724a000-7f2e9726c000 r-xp 00000000 08:05 14314443     /lib/x86_64-linux-gnu/ld-2.15.so 
7f2e97443000-7f2e97446000 rw-p 00000000 00:00 0 
7f2e97468000-7f2e9746c000 rw-p 00000000 00:00 0 
7f2e9746c000-7f2e9746d000 r--p 00022000 08:05 14314443     /lib/x86_64-linux-gnu/ld-2.15.so 
7f2e9746d000-7f2e9746f000 rw-p 00023000 08:05 14314443     /lib/x86_64-linux-gnu/ld-2.15.so 
7fffa6d43000-7fffa6d64000 rw-p 00000000 00:00 0       [stack] 
7fffa6dff000-7fffa6e00000 r-xp 00000000 00:00 0       [vdso] 
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0     [vsyscall] 

Мы поражаем Enter и перейти к в глубоко вложенных вызовов .

Я получил 0x7fffa6d60ba0 и 0x7fffa6582ff0 на моем терминале в качестве адреса buf в 1-й и 1001-го рекурсивного вызова foo(). Оба они попадают в область [stack] (7fffa6582000-7fffa6d64000; 0x7e2000 == 8 MB). Но учтите, что это было ранее 7fffa6d43000-7fffa6d64000; 0x21000 == 132 КБ.

$ cat /proc/`pidof mappingTest`/maps 
00400000-00401000 r-xp 00000000 08:05 21687266       /home/nodakai/prog/exp/mappingTest 
00600000-00601000 r--p 00000000 08:05 21687266       /home/nodakai/prog/exp/mappingTest 
00601000-00602000 rw-p 00001000 08:05 21687266       /home/nodakai/prog/exp/mappingTest 
7f2e96e8a000-7f2e9703f000 r-xp 00000000 08:05 14314431     /lib/x86_64-linux-gnu/libc-2.15.so 
7f2e9703f000-7f2e9723f000 ---p 001b5000 08:05 14314431     /lib/x86_64-linux-gnu/libc-2.15.so 
7f2e9723f000-7f2e97243000 r--p 001b5000 08:05 14314431     /lib/x86_64-linux-gnu/libc-2.15.so 
7f2e97243000-7f2e97245000 rw-p 001b9000 08:05 14314431     /lib/x86_64-linux-gnu/libc-2.15.so 
7f2e97245000-7f2e9724a000 rw-p 00000000 00:00 0 
7f2e9724a000-7f2e9726c000 r-xp 00000000 08:05 14314443     /lib/x86_64-linux-gnu/ld-2.15.so 
7f2e97443000-7f2e97446000 rw-p 00000000 00:00 0 
7f2e97468000-7f2e9746c000 rw-p 00000000 00:00 0 
7f2e9746c000-7f2e9746d000 r--p 00022000 08:05 14314443     /lib/x86_64-linux-gnu/ld-2.15.so 
7f2e9746d000-7f2e9746f000 rw-p 00023000 08:05 14314443     /lib/x86_64-linux-gnu/ld-2.15.so 
7fffa6582000-7fffa6d64000 rw-p 00000000 00:00 0       [stack] 
7fffa6dff000-7fffa6e00000 r-xp 00000000 00:00 0       [vdso] 
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0     [vsyscall] 

Вы можете получить больше удовольствия с инлайн сборки, как это:

#define PEEK_ESP(reg)   \ 
    __asm__ __volatile__ (  \ 
     "movq %%rsp, %0"  \ 
     : "=r"(reg)    \ 
    ) 
... 
void *p; 
PEEK_ESP(p); 
Смежные вопросы