Если вы находитесь в 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);
Что о вызове sbrk() дважды и тестирование ли увеличение или уменьшение адреса? – Jens