Простой ответ: Пространство в стеке ограничено. Вы можете ожидать, что сможете выделить 1 ГБ в куче, но не можете ожидать, что сможете выделить такой же объем в стеке.
Первый вариант int x[size];
использует стек. Таким образом, вы можете обнаружить, что ваша программа вылетает из-за segfault, если size
велико. Распределение происходит путем простого уменьшения регистра указателя стека вашего процессора. Если вы уменьшите его слишком сильно, ядро просто рассмотрит ваш следующий доступ к памяти стека как доступ за пределы и уничтожит ваш процесс. Невозможно обнаружить это состояние до того, как вас действительно застрелят, или вылечиться от него упорядоченным образом. Ядро просто стреляет в вас без предупреждения.
Второй вариант int* x = new int[size];
использует кучу. Таким образом, вы можете ожидать, что выделение будет выполнено успешно, пока имеется достаточно свободной оперативной памяти для резервного копирования. operator new()
будет явно запрашивать память у ядра упорядоченным образом, и ядро либо подчинится, либо сообщит о недоступности такого большого объема памяти упорядоченным образом. В случае ошибки operator new()
продолжит генерировать исключение, которое вы можете поймать и обработать по своему усмотрению.
Кроме того:
если ваше ядро чрезмерно выделяет свою память (как любой современный Linux), вы не гарантированно получите исключение в случае ошибки. Ядро просто ответит "хорошо", когда operator new()
запрашивает у него память, фактически не предоставляя ее, и позже может обнаружить, что не может выполнить свои обещания. Когда это произойдет, он вызовет OOM-убийцу (убийцу нехватки памяти), который стреляет в некоторые процессы на основе некоторой эвристики. Так что никогда не ожидайте, что вас не расстреляют за чрезмерное потребление памяти.
На самом деле это оптимизация, позволяющая фактически использовать всю доступную память: во-первых, многие программы на самом деле не используют всю выделяемую ими память (например, выделяют большой буфер, а используют только его части). Во-вторых, невозможно узнать, какая из сопоставленных страниц COW (Copy-On-Write) действительно нуждается в копировании. Ядро не знает, сколько памяти потребуется в будущем, оно знает только, достаточно ли памяти в данный момент.
TL;DR:
Используйте int x[size];
только в том случае, если вы можете доказать, что size
никогда не превысит небольшое максимальное значение. Если size
находится в диапазоне от 10 до 100 (и сам тип не безумно большой), дерзайте. Используйте int* x = new[size];
во всех остальных случаях.
person
cmaster - reinstate monica
schedule
19.02.2018
std::vector
< /а>. - person Some programmer dude   schedule 19.02.2018-pedantic
... - person StoryTeller - Unslander Monica   schedule 19.02.2018