C ++ Некоторые вопросы стека - PullRequest
3 голосов
/ 02 июля 2011

Позвольте мне начать с того, что я прочитал этот учебник и прочитал этот вопрос .Мои вопросы:

  1. Насколько большим может стать стек?Это зависит от процессора / архитектуры / компилятора?

  2. Есть ли способ точно узнать, сколько памяти доступно для моего стека функций / классов и сколько в настоящее время используется, чтобы избежатьпереполнения?

  3. Используя современные компиляторы (скажем, gcc 4.5) на современном компьютере (скажем, 6 ГБ ОЗУ), нужно ли беспокоиться о переполнении стека или это уже в прошлом?

  4. Является ли фактическая память стека физически в ОЗУ или в кэш-памяти ЦП?

  5. Насколько быстрее сравниваются доступ к памяти стека и чтениенаваливать доступ и читать?Я понимаю, что время зависит от компьютера, поэтому соотношение достаточно.

  6. Я читал, что не рекомендуется размещать большие переменные / объекты в стеке.Сколько это слишком большой? Этот вопрос здесь дается ответ 1 МБ для потока в Win32.Как насчет темы в Linux amd64?

Я прошу прощения, если на эти вопросы уже задавались и отвечали, любая ссылка приветствуется!

Ответы [ 3 ]

8 голосов
/ 02 июля 2011
  1. Да, ограничение на размер стека варьируется, но если вас волнует, вы вероятно делаете что-то не так.
  2. Как правило, нет, вы не можете получить информацию о том, какмного памяти доступно вашей программе.Даже если бы вы могли получить такую ​​информацию, она обычно устареет, прежде чем вы сможете ее использовать.
  3. Если вы разделяете доступ к данным между потоками, тогда да, вам обычно нужно сериализовать доступ, если они не предназначены только для чтения..
  4. Вы можете передать адрес объекта, выделенного в стеке, другому потоку, и в этом случае вам (снова) придется сериализоваться, если доступ не предназначен только для чтения.
  5. Вы, конечно, можетепереполнение стека даже на современной машине с большим объемом памяти.Стек часто ограничен лишь небольшой долей общей памяти (например, 4 МБ).
  6. Стек выделяется как системная память, но обычно используется достаточно, чтобы, по крайней мере, верхняя или две страницы обычно былив кеше в любой момент времени.
  7. Быть частью стека и кучи не имеет прямого отношения к скорости доступа - эти два типа обычно находятся в одинаковых микросхемах памяти, и часто даже по разным адресам в одной и той же памятичип.Основное отличие состоит в том, что стек обычно является непрерывным и интенсивно используемым, так как верхние несколько страниц почти всегда будут в кеше.Память на основе кучи, как правило, фрагментирована, поэтому вероятность получения данных, которых нет в кэше, гораздо выше.
  8. Мало что изменилось в отношении максимального размера объекта, который вы должны выделить в стеке.Даже если стек может быть больше, нет особых причин выделять там огромные объекты.
  9. Основной способ избежать утечек памяти в C ++ - это RAII (AKA SBRM, управление ресурсами на основе стека).
  10. Интеллектуальные указатели сами по себе являются большой темой, и Boost предоставляет несколько видов.По моему опыту, коллекции имеют большее значение, но основная идея в основном одинакова в любом случае: избавить программиста от отслеживания всех обстоятельств, когда определенный объект может использоваться или должен быть освобожден.
3 голосов
/ 02 июля 2011

1. Насколько большим может быть стек?Это зависит от процессора / архитектуры / компилятора?

Размер стека ограничен объемом памяти на платформе и объемом памяти, выделенным процессуоперационной системы.

2. Есть ли способ точно узнать, сколько памяти доступно для моего стека функций / классов и сколько в настоящее время используется, чтобы избежать переполнения?

Нет средств на C или C ++ для определения объема доступной памяти.Для этого могут быть специальные функции платформы.В целом, большинство программ пытаются выделить память, а затем предлагают решение для случая, когда распределение не удается.

3. Использование современных компиляторов (скажем, gcc 4.5) на современном компьютере (скажем, 6 ГБ оперативной памяти), мне нужно беспокоиться о переполнении стека или это уже в прошлом?

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

4. Физически ли фактическая память стека находится в ОЗУ или в кэш-памяти ЦП?

Платформа зависит.Некоторые процессоры могут загружать свой кэш локальными переменными в стеке.Широкий выбор сценариев на эту тему.Не определено в спецификации языка.

5. Насколько быстрее доступ к памяти стека и чтение по сравнению с доступом к куче и чтением?
Я понимаю, что время зависит от компьютера, поэтому достаточно соотношения.

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

6. Я читал, что не рекомендуется размещать большие переменные / объекты в стеке.Сколько это слишком большой?На этот вопрос здесь дается ответ 1 Мб для ветки в win32.Как насчет потока в Linux amd64?

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

Стек также содержит информацию об адресах функций.Это одна из главных причин не размещать много объектов локально.Некоторые компиляторы имеют меньшие ограничения для стеков, чем для кучи или глобальных переменных.Предполагается, что вызовы вложенных функций требуют меньше памяти, чем большие массивы данных или буферы.

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

2 голосов
/ 02 июля 2011

1-2: на некоторых встроенных процессорах размер стека может быть ограничен несколькими килобайтами; на некоторых машинах он может расширяться до гигабайт. Не существует независимого от платформы способа узнать, насколько большим может стать стек, в некоторой степени, потому что некоторые платформы способны расширять стек, когда достигают предела; успех такой операции не всегда может быть предсказан заранее.

3: Эффект почти одновременной записи или записи в одном потоке, которые происходят почти одновременно с чтением в другом, в значительной степени непредсказуем при отсутствии блокировок, мьютексов или других подобных устройств. Можно предположить некоторые вещи (например, если один поток читает «int» в куче, в то время как другой поток меняет его с 4 на 5, первый поток может видеть 4 или 5; на большинстве платформ это будет гарантировано не видеть 27).

4: Некоторые платформы разделяют адресное пространство стека между потоками; другие нет. Передача указателей на объекты в стеке обычно является плохой идеей, поскольку внешний поток, получающий указатель, не сможет гарантировать, что цель находится в области видимости и не выйдет из области видимости.

5: Как правило, не нужно беспокоиться о стековом пространстве в любой подпрограмме, которая написана для ограничения рекурсии до разумного уровня. Однако нужно беспокоиться о возможности дефектных структур данных, вызывающих бесконечную рекурсию, которая уничтожит любой стек независимо от его размера. Следует также помнить о возможности неприятного ввода, который может привести к гораздо большей глубине стека, чем ожидалось. Например, компилятор, использующий синтаксический анализатор с рекурсивным спуском, может подавиться, если передать файл, содержащий миллиард повторений последовательности «1+ (». Даже если на машине есть гигабайт стекового пространства, если каждое вложенное подвыражение использует 64 байта стек, вышеупомянутый файл в три гигабайта мог убить его.

6: стек обычно хранится в ОЗУ и / или кеше; Части, к которым недавно обращались, обычно находятся в кеше, а части, к которым обращались недавно, будут в основной памяти. Как правило, то же самое относится и к областям хранения кода, кучи и статического хранилища.

7: Это очень зависит от системы; Как правило, «нахождение» чего-либо в куче занимает столько же времени, сколько и доступ к нескольким вещам в стеке, но во многих случаях многократный доступ к различным частям одного и того же объекта кучи может быть столь же быстрым, как и доступ к объекту стека.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...