New [] не уменьшает доступную память до заполнения

Это в С++ на 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.

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

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

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

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

Ура!

Edit:

Я не хочу знать, как мы должны использовать Vectors, это не OO/С++/текущий способ делать вещи и т.д. Я просто хочу знать, почему это происходит так, как есть чем предлагать альтернативные способы его попробовать.

Ответ 1

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

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

Ответ 2

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

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

Ответ 3

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

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

Некоторые операционные системы могут пытаться перекомпилировать выделение памяти, а затем пропустить позже. Это не соответствует стандарту языка С++.