Интерпретация расположения значений в адресном пространстве 32-битного процесса Linux - PullRequest
0 голосов
/ 12 января 2019

Я пытаюсь разобраться с адресным пространством процесса Linux и вижу в этом вопросе хорошую возможность разобраться с вещами. Может ли кто-нибудь посоветовать, в какой части адресного пространства процесса находится следующее?

Код, который реализует strcpy - я полагаю, что это в разделе DLL.

Переменная p1 - я считаю, что это находится в куче, так как она динамически распределяется.

Местоположение указывало на * p1.

Место, на которое указывает * p2.

Строковый литерал "Я строка".

Заранее спасибо!

int main()
{

    char *p1 = NULL;
    void *p2 = (void *)0xDDDDDDDD;
    p1 = malloc(100);
    strcpy(p1, "I am a string");

    return (0);
}

1 Ответ

0 голосов
/ 12 января 2019

Структура виртуальной памяти процесса Linux выглядит следующим образом:

diagram of process layout

(Источник: Википедия, Дугкт .)

Процесс делится на разные сегменты памяти, в зависимости от того, как вы распределяете память. В Википедии есть хорошее объяснение того, для чего каждый из них.

Давайте пройдемся по программе, строка за строкой.

Строки 1-2: объявить 2 указателя, которые хранятся в стеке.

Строка 3: выделить 100 байтов в куче. Сделайте точку p1 на это. Другими словами: p1 - указатель (находится в стеке) на часть памяти (находится в куче).

Строка 4: скопировать строковый литерал (хранящийся в текстовом разделе) в часть памяти (расположенную в куче).

Строка 5: возврат. Это освобождает место для указателей, но не освобождает то, на что они указывают. Область памяти, на которую указывает p2, не освобождается, поэтому происходит утечка памяти. (Хотя программа заканчивается, поэтому здесь это не имеет значения.)

Код, который реализует strcpy - я полагаю, это в разделе DLL.

Краткий ответ: «текстовый раздел».

Полный ответ: «Это зависит от настроек вашего компилятора».

Допустим, вы статически связываете свою программу:

$ gcc -static test.c
$ ./a.out & pmap $!
0000000000400000      4K r---- a.out
0000000000401000    492K r-x-- a.out
000000000047c000    140K r---- a.out
00000000004a0000     24K rw--- a.out
00000000004a6000      4K rw---   [ anon ]
00000000007df000    140K rw---   [ anon ]
00007ffc6031b000    132K rw---   [ stack ]
00007ffc60358000      8K r----   [ anon ]
00007ffc6035a000      8K r-x--   [ anon ]
ffffffffff600000      4K r-x--   [ anon ]

Вторая строка, 0000000000401000 492K r-x-- a.out - текстовый раздел. Обратите внимание, что она довольно большая для нашей 5-строчной программы. Это потому, что мы помещаем библиотеки, которые мы используем, в наш текстовый раздел.

С другой стороны, вы можете связать его динамически:

$ gcc test.c
$ ./a.out & pmap $!
[1] 5637
5637:   ./a.out
0000555943977000      4K r---- a.out
0000555943978000      4K r-x-- a.out
0000555943979000      4K r---- a.out
000055594397a000      4K r---- a.out
000055594397b000      4K rw--- a.out
00005559442ca000    132K rw---   [ anon ]
00007f3af067b000    136K r---- libc-2.27.so
00007f3af069d000   1304K r-x-- libc-2.27.so
00007f3af07e3000    300K r---- libc-2.27.so
00007f3af082e000     16K r---- libc-2.27.so
00007f3af0832000      8K rw--- libc-2.27.so
00007f3af0834000     16K rw---   [ anon ]
00007f3af0838000      8K rw---   [ anon ]
00007f3af085e000      4K r---- ld-2.27.so
00007f3af085f000    120K r-x-- ld-2.27.so
00007f3af087d000     32K r---- ld-2.27.so
00007f3af0885000      4K r---- ld-2.27.so
00007f3af0886000      4K rw--- ld-2.27.so
00007f3af0887000      4K rw---   [ anon ]
00007fff10f99000    132K rw---   [ stack ]
00007fff10fc2000      8K r----   [ anon ]
00007fff10fc4000      8K r-x--   [ anon ]
ffffffffff600000      4K r-x--   [ anon ]

Обратите внимание на две вещи: наш текстовый раздел (0000555943978000 4K r-x-- a.out) теперь крошечный. Также мы можем видеть, что libc загружен в отдельный раздел памяти. (Диаграмма, которую я показал выше, скрывает эту деталь - более полная диаграмма здесь: https://unix.stackexchange.com/questions/466443/do-memory-mapping-segment-and-heap-grow-until-they-meet-each-other)

...