Почему mallo c не выделяет память, пока я не достигнет определенного порога? - PullRequest
2 голосов
/ 02 августа 2020
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int main(int argc, char *argv[])
{
        size_t sz = atol(argv[1]);
        char *arr = malloc(sz);

        sleep(10);
}

Я скомпилировал этот код и попытался запустить его, использовал pmap, чтобы увидеть отображение памяти программы.

Когда я использую какое-то большое число, например 1024000, я получаю отображение вот так:

3901:   ./alloc_program 1024000
0000560192f43000      4K r---- alloc_program
0000560192f44000      4K r-x-- alloc_program
0000560192f45000      4K r---- alloc_program
0000560192f46000      4K r---- alloc_program
0000560192f47000      4K rw--- alloc_program
0000560192fac000    132K rw---   [ anon ]
00007f75b69e9000   1004K rw---   [ anon ]     <---- I believe this is the allocated memory
00007f75b6ae4000    148K r---- libc-2.31.so
00007f75b6b09000   1504K r-x-- libc-2.31.so
00007f75b6c81000    296K r---- libc-2.31.so
00007f75b6ccb000      4K ----- libc-2.31.so
00007f75b6ccc000     12K r---- libc-2.31.so
00007f75b6ccf000     12K rw--- libc-2.31.so
00007f75b6cd2000     24K rw---   [ anon ]
00007f75b6ce7000      4K r---- ld-2.31.so
00007f75b6ce8000    140K r-x-- ld-2.31.so
00007f75b6d0b000     32K r---- ld-2.31.so
00007f75b6d14000      4K r---- ld-2.31.so
00007f75b6d15000      4K rw--- ld-2.31.so
00007f75b6d16000      4K rw---   [ anon ]
00007ffe2b26e000    132K rw---   [ stack ]
00007ffe2b318000     12K r----   [ anon ]
00007ffe2b31b000      4K r-x--   [ anon ]
ffffffffff600000      4K --x--   [ anon ]
 total             3496K

Я предполагаю, что отмеченная строка - это память, выделенная mallo c (возможно, я ошибаюсь). Но когда я использую небольшое число, например 10240, я не вижу, чтобы что-то было выделено:

3879:   ./alloc_program 10240
000055e428e26000      4K r---- alloc_program
000055e428e27000      4K r-x-- alloc_program
000055e428e28000      4K r---- alloc_program
000055e428e29000      4K r---- alloc_program
000055e428e2a000      4K rw--- alloc_program
000055e42a257000    132K rw---   [ anon ]
00007f102332c000    148K r---- libc-2.31.so
00007f1023351000   1504K r-x-- libc-2.31.so
00007f10234c9000    296K r---- libc-2.31.so
00007f1023513000      4K ----- libc-2.31.so
00007f1023514000     12K r---- libc-2.31.so
00007f1023517000     12K rw--- libc-2.31.so
00007f102351a000     24K rw---   [ anon ]
00007f102352f000      4K r---- ld-2.31.so
00007f1023530000    140K r-x-- ld-2.31.so
00007f1023553000     32K r---- ld-2.31.so
00007f102355c000      4K r---- ld-2.31.so
00007f102355d000      4K rw--- ld-2.31.so
00007f102355e000      4K rw---   [ anon ]
00007fff1d513000    132K rw---   [ stack ]
00007fff1d570000     12K r----   [ anon ]
00007fff1d573000      4K r-x--   [ anon ]
ffffffffff600000      4K --x--   [ anon ]
 total             2492K

1 - Почему оно не выделяется, когда размер памяти относительно мал?

2 - Почему размер выделенной памяти не совпадает? При первом запуске он показывает, что размер равен 1004KB, в то время как я выделил только 1000KB.

Ответы [ 2 ]

4 голосов
/ 02 августа 2020

1 - Почему она не выделяется при относительно небольшом размере памяти?

Задача функции malloc - предоставить приложению память, когда оно запрашивает для этого. Теоретически malloc может, как вы предлагаете, просто перенаправлять все запросы на выделение памяти в ядро ​​ операционной системы, чтобы оно действовало только как оболочка для распределителя памяти ядра. Однако это имеет следующие недостатки:

  1. Ядро предоставляет только большие объемы памяти одновременно, по крайней мере, одну страницу памяти, которая, в зависимости от конфигурации операционная система, обычно не менее 4096 байт. Следовательно, если приложение запрашивает только 10 байт памяти, много памяти будет потрачено впустую.
  2. Системные вызовы дороги с точки зрения производительности ЦП.

По этим причинам, для malloc более эффективно не пересылать запросы выделения памяти непосредственно ядру, а действовать как посредник между запросами выделения памяти приложения и ядром. Он запрашивает у ядра больший объем памяти, чтобы удовлетворить множество меньших запросов на выделение памяти от приложения.

Следовательно, только при одновременном запросе большого количества памяти, malloc пересылает это запрос выделения памяти к ядру.

2 - Почему размер выделенной памяти не такой же? При первом запуске он показывает, что размер равен 1004KB, в то время как я выделил только 1000KB.

Распределитель malloc должен отслеживать все выделения памяти, которые он предоставил для приложение, а также отслеживать все выделения памяти, которые ему были предоставлены ядром. Для хранения этой информации требуется немного дополнительной памяти. Это дополнительное пространство называется «накладными расходами».

3 голосов
/ 02 августа 2020

То, что вы видите в выводе pmap, почти наверняка является добавлением , необходимым для malloc арены для удовлетворения более крупных запросов, а не любым одиночным запросом.

Арена - это пул памяти, из которого распределяются выделения, и есть большая вероятность, что он начинается с определенного размера и расширяется только по запросу.

Например, если начальная арена составляет 1000 КБ , любое выделение, которое не исчерпывается, не требует дополнительного места на арене. Если вы выполните это пространство, процесс попытается запросить дополнительную арену из базовой среды, чтобы удовлетворить дополнительный спрос.

Что касается того, почему размер не тот, что вы просили, есть (по крайней мере) две возможные причины. Во-первых, арена - это не просто память, выделенная для ваших целей, она также содержит управляющую информацию, чтобы можно было правильно управлять памятью (размеры, контрольные суммы, указатели, список свободных мест и т. Д.).

Во-вторых, malloc может быть перераспределено в ожидании, что это не будет последний запрос, который исчерпывает текущую арену. Некоторые стратегии выделения памяти go вплоть до удвоения текущего размера арены при запросе большего количества, чтобы снизить затраты на это.

...