Огромное распределение памяти: стек против кучи - PullRequest
0 голосов
/ 11 сентября 2018

Я сделал структуру, которая требует 1 ГБ памяти. Когда я разместил его в куче, программа запустилась быстро, и я увидел в Диспетчере приложений, что объем используемой памяти увеличился до этой суммы, но когда я выделил ее в стеке, как простая переменная, приложению потребовалось гораздо больше времени для запуска и в диспетчере приложений я увидел, что он не использует такой объем памяти (всего несколько килобайт). Почему это? Означает ли это, что рекомендуется хранить большой объем данных в куче? Это быстрее для этого случая? Я знаю, что обычно выделение памяти в стеке происходит быстрее из-за сопоставления и т. Д., Но в этом случае это было странно. Может кто-нибудь объяснить мне это? Заранее спасибо!

Ответы [ 2 ]

0 голосов
/ 11 сентября 2018

Да, рекомендуется делать большие выделения динамически - потому что тогда вы сможете изящно справиться с неудачей ( обязательное примечание по терминологии ).

Например, это:

void might_throw(size_t sz) {
  std::vector<int> v(sz);
  // ...
}

выдаст std::bad_alloc, если произойдет сбой при достаточно большом sz, что означает, что у меня есть возможность перехватить исключение и повторить попытку с меньшим числом.Даже если мне не удастся восстановить, разматывание стека позволяет безопасно очищать мои другие объекты.

И наоборот

void will_just_die() {
  int a[SomeEnormousConstant];
  // ...
}

не имеет механизма восстановления, если a не может быть на самом делесоздано.Программа просто аварийно завершит работу, без разматывания стека или (стандартного) механизма обработки ошибок.

Это может произойти немедленно, или это может произойти, только если вы действительно попытаетесь получить доступ к большему количествуa чем можно было бы успешно выделить.Если вам очень не повезло, он может даже работать , но что-то сломать.


Детали того, как данное распределение отображается внешне, очень зависят от ОС, и яя не уверен, что вы используете - является ли диспетчер приложений OSX?

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

Если автоматическое ("стек") просто выполняет арифметику с указателем фрейма и снова полагается на ленивое распределение физических страниц, это не повлияетлибо виртуальный, либо физический размер (опять же, пока вы не попытаетесь реально получить доступ к этой памяти).

Я не знаю, почему запуск автоматической версии займет больше времени - вам нужно будет предоставить MCVE , для которого это было фактически воспроизводимо, а также сведения о вашей ОС / платформе, чтобы получить ответ на этот вопрос.

0 голосов
/ 11 сентября 2018

Размер стека обычно составляет от одного до нескольких мегабайт по умолчанию в типичных настольных системах. Вероятно, меньше на встроенных устройствах.

Если вы выделяете больше памяти, чем умещается в стеке, операционная система обычно завершает программу, как только вы пытаетесь получить доступ к памяти.

Означает ли это, что рекомендуется хранить большой объем данных в куче?

Рекомендуется использовать свободное хранилище (динамическое выделение) для большого объема данных, поскольку большой объем данных может переполнить стек.

Диспетчер приложений. Я видел, что он не использует такой объем памяти (всего несколько килобайт).

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

...