malloc () в C и использовании памяти - PullRequest
2 голосов
/ 17 февраля 2012

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

Я использовал следующую простую программу и у меня есть несколько вопросов:

int main(void)
{
    char * ptr;
    int x = 100;

    while(1)
    {
        ptr = (char *) malloc(x++ * sizeof(char) / 2);
        printf("%p\n",ptr);
    }

    return 0;
}

1)Почему при использовании больших типов данных (int, unsigned long long int, long double) процесс будет использовать меньше памяти, но при меньших типах данных (int, char) он будет использовать больше?

2) Когдапри запуске программы она прекратила бы выделять память после того, как достигла определенного объема (~ 592 МБ в Windows 7, 64-разрядная версия с файлом подкачки ОЗУ 8 ГБ, установленным как управляемый системой).Выходные данные печати, если показали 0, что означает NULL.Почему он прекращает выделять память после достижения этого порога и не исчерпывает системную память и подкачку?

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

Я пробовал код на ядре Linux 2.6.32-5-686 с похожими результатами.

Любая помощь и объяснения приветствуются.

Спасибо,

Ответы [ 4 ]

5 голосов
/ 17 февраля 2012

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

2) Это имеет смысл, поскольку в многозадачной системе вы не единственный пользователь, и ваш процесс - не единственный запущенный процесс, есть много других процессов, которые совместно используют ограниченный набор ресурсов, включая память. Если ОС позволяла одному процессу распределять всю необходимую память без каких-либо ограничений, то это не совсем хорошая ОС, верно?

Наконец, в Linux ядро ​​не выделяет никаких страниц физической памяти до тех пор, пока вы фактически не начнете использовать эту память, поэтому простой вызов malloc фактически не потребляет физической памяти, кроме той, которая требуется для отслеживания Само выделение конечно. Я не уверен насчет Windows.

Edit: В следующем примере выделяется 1 ГБ виртуальной памяти

#include <stdio.h>
int main(int agrc, char **argv)
{
    void *p = malloc(1024*1024*1024);
    getc(stdin);
}

Если вы бежите сверху, вы получаете

top -p `pgrep test`
PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND
20   0 1027m  328  252 S    0  0.0   0:00.00 test

Если вы измените malloc на calloc и снова запустите top, вы получите

top -p `pgrep test`
PR   NI VIRT  RES  SHR S %CPU %MEM    TIME+ COMMAND              
20   0  1027m 1.0g 328 S    0  1.3   0:00.08 test
1 голос
/ 17 февраля 2012

1) При выделении памяти каждое выделение занимает место запрошенной памяти плюс размер кадра кучи. Смотрите связанный вопрос здесь

2) Размер любого одиночного malloc в Windows ограничен _HEAP_MAXREQ. См. этот вопрос для получения дополнительной информации и некоторых обходных путей.

1 голос
/ 17 февраля 2012

Как вы читаете использование памяти?

1) При выделении с помощью char вы выделяете меньше памяти на выделение, чем, например, при long (обычно на четверть больше, но это зависит от машины) Поскольку большинство инструментов использования памяти, внешних по отношению к самой программе, не показывают выделенную память, а на самом деле использует память, оно будет отображать только служебные данные, которые использует сам malloc () вместо неиспользованной памяти, которую вы используете malloc.

Больше ассигнований, больше накладных расходов.

Вы должны получить совсем другой результат, если заполните блок malloc данными для каждого выделения, чтобы фактически использовалась память.

2) Я полагаю, вы читаете это из того же инструмента? Попробуйте подсчитать, сколько байтов вы фактически выделите, и вместо правильных «служебных данных malloc» должно отображаться правильное количество.

0 голосов
/ 17 февраля 2012

1) Это может быть связано с тем, что память разбита на страницы и что каждая страница имеет одинаковый размер.Если ваши данные не помещаются на одной странице и «попадают» между двумя страницами, я думаю, что это перемещение в начало следующей страницы, что приводит к потере места в конце предыдущей страницы.* 2) Порог меньше, потому что я думаю, что каждая программа ограничена определенным объемом данных, который не является максимальным объемом вашей памяти.

...