Есть ли ограничение на общий размер переменных в стеке? - PullRequest
4 голосов
/ 12 января 2010

При кодировании мы должны учитывать какое-то ограничение на общий размер переменных, создаваемых в стеке? Если да, на каком основании мы должны решить это? Это зависит от ОС, доступности памяти и т. Д.? Есть ли варианты компилятора, которые могут это проверить?

Любые указатели в направлении также будут полезны.

Ответы [ 2 ]

7 голосов
/ 12 января 2010

Это одна из менее удобных для пользователя областей стандарта C.

Это все полностью зависит от реализации, и практически невозможно сделать «должным образом». Стандарт C не гарантирует, какие автоматические переменные вы можете определить, не выбрасывая стек, или что происходит, когда вы это делаете, или каким-либо способом измерения использования стека или указания размера стека, или каким-либо способом определения того, что у вас заканчивается стек, возможно, с непредсказуемыми результатами. Стандарт даже не упоминает слово «стек».

Итак, вы должны помнить о том, сколько стека вы используете, но сколько это слишком много, может быть несколько килобайт или даже меньше во встроенной системе и 1 МБ или больше в настольной системе. В Windows вы не заботитесь о стеке - если вы не размещаете на нем обширные массивы или не возвращаетесь на глубину, равную размеру некоторого массива или списка, то все будет в порядке. На ограниченных системах не всегда хорошая идея поместить даже имя файла в стек. Но если вы когда-нибудь поместите в стек только встроенные типы и крошечные массивы и структуры, и если вы когда-нибудь только вернетесь к глубине log N, то снова все будет в порядке практически везде. Надеюсь, у вас будет явный сбой, если вы не в порядке, но вы не уверены.

Самое критическое время - это когда вы переносите код на новую систему - если вы не можете оценить, что использование стека «не очень», вам нужно тщательно протестировать. По этой причине, если вы беспокоитесь о переносимости в ограниченные системы, вы должны быть осторожны с использованием стека. Что касается того, что означает «консервативный», это в некотором роде зависит от того, что означает «ограниченный», но если вас интересуют уровни «ограниченного» для мобильных телефонов, то размер файла соответствует тому, о чем вы, возможно, думаете, «следует вместо этого это будет в куче? ", но, конечно, контекст имеет большое значение: если ваш код обработки файлов имеет 10 слоев, изменяя имя файла на каждом слое, то вы не хотите делать это в стеке. Если у него всего пара слоев, и вы знаете, что он не будет вызываться кодом, в котором уже есть что-то большое в стеке, вы, вероятно, сойдете с рук.

Хотя я говорю «телефоны», современные смартфоны ближе к настольной модели «о, просто используйте то, что вам нужно, все будет хорошо». Если вы программируете что-то, похожее на PIC (и настаиваете на написании C), тогда в основном забудьте о переносимых предположениях и точно отслеживайте, какой стек вы используете, по сравнению с тем, что доступно.

Я не помню, чтобы когда-либо сталкивался с защищенной ОС, которая работает так, как описывает 0x6adb015, поэтому вы даже не можете сказать: «Неважно, использую ли я стек или кучу, они все приходят из одного пула в конец". Они не обязательно. Две основные модели, с которыми я столкнулся:

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

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

Таким образом, стек может быть более ограниченным ресурсом, чем куча. Как говорит Митч Уит, параметры компилятора (или компоновщика) могут варьироваться в размере этого региона, подробности смотрите в руководстве. ОС также может предоставлять параметры времени выполнения, такие как ulimit. Я бы добавил, что API-интерфейсы потоков позволяют указать размер стека для нового потока. Опять же, это полностью зависит от реализации.

4 голосов
/ 12 января 2010

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

Короче говоря, размер стека связан с картой памяти вашего процесса.

+------
| stack
|  |
|  V
+------
|
| free space
|
+-----
|  ^
|  |
| heap
+------

Это также должно быть верно для встроенных систем.

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