2009-12-16 2 views
13

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

+36

Когда закончите! –

+0

Когда вы сталкиваетесь с переполнением стека? :-) –

ответ

4

Я никогда не беспокоюсь об этом. Если есть переполнение стека, я скоро узнаю об этом. Кроме того, на C++ на самом деле очень сложно создавать очень большие объекты в стеке. О единственный способ сделать это:

struct S { 
    char big[1000000]; 
}; 

но использование станд :: строка или станд :: вектор делает эту проблему уйти.

+6

Очевидно, что вы не отлаживали переполнение стека на встроенных системах или тому подобное. Иногда они могут быть самыми трудными ошибками для отслеживания. На обычной настольной ОС это может показаться не очень удачным, но в других системах вы можете не узнать об этом до тех пор, пока * после * ваш стек не будет полностью поврежден. И тогда вы не получите стек, потому что стек так запутан. Это может занять много времени, чтобы понять, что это * * переполнение стека. Затем поиск * как *, и какая задача/поток/процесс вызвали его, может снова стать крайне неприятным делом. Поверьте, это стоит беспокоиться. –

+0

Почему вы обертываете его внутри структуры? – toto

+0

Поскольку ОП спрашивал об объектах, по которым я это понял, он имел в виду «экземпляры класса или структуры» - я знаю, что он имеет другие значения. – 2009-12-17 09:05:24

3

Разве вы не должны избегать использования стека для выделения больших объектов в первую очередь? Используйте кучу, нет?

7

Вы начинаете беспокоиться о размере стека, когда

  • кто-то в вашей команде хитро изобретает рекурсивную функцию, которая идет дальше и дальше и дальше ...
  • вы создаете нить завод и вдруг понадобится десятикратное из стека, который вы использовали для нужно (каждый поток должен стек => тем больше потоков, тем меньше свободного места остается для заданного размера стека)
3

мой опыт: при использовании рекурсивных функций, принимать уход за стеком размер!!

+5

Это не мой опыт. Что вы * делаете, чтобы «позаботиться» о размере стека, когда у вас есть рекурсивная функция? Я ничего не делаю с размером стека. Когда я получил переполнение стека в рекурсивной функции, он всегда * был, потому что у меня была ошибка, которая оставила рекурсию неограниченной, и в этом случае увеличение размера стека только затормозило бы неизбежное. Решение состоит в том, чтобы исправить ошибку, а не менять стек. –

+0

@Rob, рассмотрим линейный график с 100 000 узлов, обход DFS дает вам поток стека. «заботиться» не означает изменение размера. я имею в виду, что вы должны знать размер, необходимый для вашей рекурсивной функции. –

11

Вы заботитесь об этом на микроконтроллере, где вам часто приходится указывать пространство стека явно (или вы получаете то, что осталось после того, как ОЗУ будет использоваться для статического распределения + любое пространство программ RAM).

13

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

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

... когда и как вы беспокоитесь о размере стека?

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

Существуют ли какие-либо эмпирические правила для определения размера стека?

  • Очень большие объекты могут взорвать стек
  • Очень глубокая рекурсия может взорвать стек размер стека
  • по умолчанию может быть слишком большим (слишком много общего объема памяти), если есть много потоков и, если вы работаете на встроенном устройстве с ограниченной памятью, и в этом случае вам может понадобиться использовать API-интерфейс O/S или компоновщик, чтобы уменьшить размер стека на поток.
2

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

CreateThread по умолчанию выделяет только 0x100000 байт для стека.

+1

http://msdn.microsoft.com/en-us/library/ms682453(VS.85).aspx говорит: «Если этот параметр равен нулю, новый поток использует размер по умолчанию для исполняемого файла» и http: // msdn.microsoft.com/en-us/library/ms686774(VS.85).aspx говорит: «Размер резервирования по умолчанию, используемый компоновщиком, составляет 1 МБ». – ChrisW

+2

Не могли бы вы объяснить, что вы подразумеваете под «компилятором»? Я почти уверен, что большинство компиляторов ничего не делают, чтобы вычислить размер стека. Вместо этого они используют только ОС по умолчанию или, если они разрешают, любой номер, который вы указываете в своей конфигурации проекта. В некоторых случаях * возможно * вычислять максимальное использование стека программой, но это невозможно в общем случае, потому что это потребует решения проблемы остановки. –

+0

High6, мое редактирование должно было исправить неверную информацию. Значение, которое вы требуете, 0x1000, составляет всего 4 КБ. Размер стека по умолчанию на самом деле 1 МБ, как показывают ссылки Криса. Пожалуйста, дайте коррекционную стойку или предоставите некоторую ссылку, почему вы считаете, что стек намного меньше, чем указано в документации. –

1

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

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

Если процессор не имеет управления памятью или блока защиты памяти, вы должны быть особенно осторожны. Но событие с каким-то MMU или MPU, аппаратное обеспечение может не обнаружить переполнение стека. Одна общая схема, резервирующая страницу под стеком, чтобы перехватить переполнение, терпит неудачу, если большой объект стека больше, чем страница. Там может быть стопка другого потока, сидящего там, и упс! вы просто создали очень неприятную, трудно найти ошибку.

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

1

При принятии решения о том, следует ли выделять объекты в стеке против кучи, есть также первоочередные проблемы, которые необходимо учитывать. Распределение памяти в стеке происходит очень быстро - это просто связано с перемещением указателя стека, тогда как динамическое распределение/освобождение с использованием new/delete или malloc/free довольно дорого, особенно в многопоточном коде, который не имеет кучи на поток. Если у вас есть функция, которая вызывается в узком цикле, вы можете ошибаться на стороне размещения больших объектов в стеке, сохраняя в себе все многопотоковые оговорки, упомянутые в других ответах, даже если это означает, что нужно увеличить стек пространство, которое большинство линкеров позволит вам сделать.

+0

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

2

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

6

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

Если это не так, то не беспокойтесь, пока ваша программа не сработает :) Если вы не распределяете серьезно огромные объекты (многие десятки KB), то это никогда не будет проблемой.

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

2

Прослушивали эту игру на Symbian: когда использовать TBuf (строка с памятью в стеке) и когда использовать HBufC (которые выделяют хранилище строк в куче, например std :: string, так что у вас есть чтобы справиться с «Оставшемся», и ваша функция нуждается в способе выхода из строя).

В то время (может быть, я еще не уверен), в потоках Symbian было 4k стека по умолчанию. Чтобы манипулировать именами файлов, вам нужно рассчитывать на использование до 512 байт (256 символов).

Как вы можете себе представить, полученная мудрость «никогда не помещала имя файла в стек». Но на самом деле оказалось, что вы можете уйти с ним гораздо чаще, чем вы думаете. Когда мы начали запускать реальные программы (TM), например игры, мы обнаружили, что в любом случае нам нужен был больше, чем размер стека по умолчанию, и это было связано не с именами файлов или с другими конкретными крупными объектами, это было связано со сложностью игровой код.

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

2

Обычно вы не можете иметь большие объекты в стеке. Они почти всегда используют кучу внутри, поэтому даже если они «находятся в стеке», их данные не являются. Даже объект с множеством членов данных, как правило, не превышает 64 байта в стеке, а остальное - в куче. Стек обычно становится проблемой в эти дни, когда у вас много потоков и много рекурсии.

3

Когда вы беспокоитесь о размере стека?

Никогда.

Если у вас проблемы с размером стека, это означает, что вы делаете что-то еще неправильно и должны исправить это, а не беспокоиться о размере стека.
Для instace:

  • Выделяя неоправданно большие структуры в стеке - не делайте этого. выделять в кучу.
  • Имея смехотворно длинную рекурсию. Я имею в виду порядок рисования изображения и итерации по пикселям с помощью рекурсии. - найти лучший способ сделать это.
1

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

Я как-то написал парсер CSV и во время игры, пытаясь получить максимальную производительность, я выделял в стек стоп-сигналы тысяч 1K буферов. Производительность была звездной, но оперативная память увеличилась примерно до 1 ГБ по сравнению с обычной 30 МБ. Это связано с тем, что каждая ячейка в файле CSV имела фиксированный размер 1K-буфера.

Как все говорят, если вы не делаете рекурсию, вам не нужно беспокоиться об этом.

0

Вы беспокоитесь об этом, когда вы пишете обратный вызов, который будет вызываться из потоков, порожденных средой выполнения, которую вы не контролируете (например, время выполнения MS RPC) с размером стека по усмотрению этой среды выполнения. Как-то like this.

0

У меня были проблемы с запуском из стека, когда:

  • Функция случайно называют себя
  • Функции использует рекурсию на глубокий уровень
  • Функция выделяет большой объект в стеке, и есть куча.
  • функция использует сложные шаблоны и компилятор разбивает

условии I:

  • Выделяют крупные объекты в куче (например, с помощью "auto_ptr Foo = новый Foo" вместо "Foo Foo".)
  • Используйте рекурсию разумно.

У меня обычно нет проблем, поэтому, к сожалению, не знаю, какие должны быть хорошие значения по умолчанию.

0

Вы начинаете беспокоиться о размере стека, когда:

  • когда ваша программа падает - как правило, эти ошибки, как правило, странно первый раз, когда вы видите их :)
  • вы работаете алгоритм, который использует рекурсию и имеет пользовательский ввод в качестве одного из его параметров (вы не знаете, сколько стека может использовать ваш алгоритм)
  • Вы работаете на встроенных платформах (или платформах, где каждый ресурс важен). Обычно на этих платформах стек выделяется до того, как будет создан процесс, поэтому должна быть сделана хорошая оценка требований к стеку.
  • Вы создаете объекты в стеке в зависимости от некоторых параметров, изменяемых по пользовательскому вводу (см. Образец ниже).
  • код, выполняемый в потоке/процессе/задаче, составляет очень, и есть много вызовов функций, которые проникают глубоко в стек и генерируют огромный стек вызовов. Обычно это происходит в больших структур, которые сочетают в себе много триггеров и обработки событий (в рамках графического интерфейса пользователя, например: receive_click-> find_clicked_window-> send_msg_to_window-> process_message-> process_click-> is_inside_region-> trigger_drawing-> write_to_file-> ...). Короче говоря, вы должны беспокоиться о стеке вызовов в случае сложного кода или неизвестных/двоичных сторонних модулей.

образец для изменяемых входных параметров:

in my_func(size_t input_param) 
{ 
    char buffer[input_param]; 
    // or any other initialization of a big object on the stack 
    .... 
} 

Совет:

  • следует отметить стек с некоторыми магическими числами (в случае, если вы выделить его), и проверить, если эти магические числа (в этом случае стека будет недостаточно для задачи/потока/процесса и, вероятно, должно быть увеличено)
1
  1. Когда код, который вы написали для PC внезапно, как предполагается запустить на мобильном телефоне
  2. Когда код портирования для запуска на мобильный телефон вдруг предполагается запустить на DSP

(И да, это реальный snafus.)

Смежные вопросы