new [] не уменьшает доступную память до заполнения - PullRequest
13 голосов
/ 17 марта 2011

Это в C ++ на CentOS 64bit с использованием G ++ 4.1.2.

Мы пишем тестовое приложение для загрузки памяти в системе n гигабайт. Идея состоит в том, что общая нагрузка системы контролируется через SNMP и т. Д. Так что это всего лишь способ осуществления мониторинга.

Однако мы видели, что просто делаем:

char* p = new char[1000000000];

не влияет на используемую память, как показано в верхней или свободной -m

Распределение памяти кажется «реальным» только после записи в память:

memcpy(p, 'a', 1000000000);   //shows an increase in mem usage of 1GB

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

p[0] = 'a';    //does not show an increase of 1GB.

Это нормально, память фактически полностью выделена? Я не уверен, что инструменты, которые мы используем (top и free -m), отображают неверные значения или что-то умное происходит в компиляторе или во время выполнения и / или в ядре.

Такое поведение наблюдается даже в отладочной сборке с отключенными оптимизациями.

Насколько я понял, новый [] сразу же выделил память. Задерживает ли среда выполнения C ++ это фактическое распределение до тех пор, пока к нему не будет получен доступ. В таком случае может ли исключение нехватки памяти быть отложено до тех пор, пока не будет фактически выполнено выделение памяти до тех пор, пока не будет осуществлен доступ к памяти?

Так как это не проблема для нас, но было бы неплохо узнать, почему это происходит именно так!

Ура!

Edit:

Я не хочу знать о том, как мы должны использовать Векторы, это не OO / C ++ / текущий способ работы и т. Д. И т. Д. Я просто хочу знать, почему это происходит именно так чем есть предложения для альтернативных способов попробовать это.

Ответы [ 3 ]

17 голосов
/ 17 марта 2011

Когда ваша библиотека выделяет память из ОС, ОС просто зарезервирует диапазон адресов в виртуальном адресном пространстве процесса.У ОС нет никаких оснований предоставлять эту память, пока вы ее не используете - как вы продемонстрировали.

Если вы посмотрите, например, /proc/self/maps, вы увидите диапазон адресов.Если вы посмотрите на верхнюю память используйте , вы ее не увидите - вы еще не используете ее.

8 голосов
/ 17 марта 2011

Пожалуйста, найдите overcommit. Linux по умолчанию не резервирует память, пока к ней нет доступа. И если в итоге вам потребуется больше памяти, чем доступно, вы не получите ошибку, но случайный процесс будет убит. Вы можете контролировать это поведение с помощью /proc/sys/vm/*.

IMO, overcommit должен быть индивидуальным, а не глобальным. И значение по умолчанию не должно быть чрезмерным.

2 голосов
/ 17 марта 2011

О второй половине вашего вопроса:

Стандарт языка не допускает каких-либо задержек при броске bad_alloc.Это должно произойти как альтернатива new [], возвращающему указатель.Это не может произойти позже!

Некоторые ОС могут попытаться переопределить выделение памяти и завершиться неудачей позже.Это не соответствует стандарту языка C ++.

...