new[] не уменьшает доступную память до заполнения
Это в 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++ это фактическое распределение до тех пор, пока к нему не будет получен доступ. В таком случае может ли исключение из-за нехватки памяти быть отложено до тех пор, пока не произойдет фактическое выделение памяти, пока не будет осуществлен доступ к памяти?
Так как это не проблема для нас, но было бы неплохо узнать, почему это происходит именно так!
Ура!
Редактировать:
Я не хочу знать о том, как мы должны использовать Векторы, это не OO / C++ / текущий способ работы и т. Д. И т. Д. Я просто хочу знать, почему это происходит, а не предлагать для альтернативных способов попробовать это.
3 ответа
Пожалуйста, найдите для overcommit. Linux по умолчанию не резервирует память до тех пор, пока к ней не будет получен доступ. И если в итоге вам потребуется больше памяти, чем доступно, вы не получите ошибку, но случайный процесс будет убит. Вы можете контролировать это поведение с /proc/sys/vm/*
,
IMO, overcommit должен быть индивидуальным, а не глобальным. И по умолчанию не должно быть чрезмерного.
Когда ваша библиотека выделяет память из ОС, ОС просто зарезервирует диапазон адресов в виртуальном адресном пространстве процесса. У ОС нет причин фактически предоставлять эту память, пока вы ее не используете - как вы продемонстрировали.
Если вы посмотрите на, например, /proc/self/maps
вы увидите диапазон адресов. Если вы посмотрите на использование памяти сверху, вы не увидите его - вы еще не используете его.
О второй половине вашего вопроса:
Стандарт языка не допускает каких-либо задержек при создании bad_alloc. Это должно произойти как альтернатива new[], возвращающему указатель. Это не может произойти позже!
Некоторые операционные системы могут пытаться перераспределить память и потерпеть неудачу позже. Это не соответствует стандарту языка C++.