| Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
| Форум программистов > C/C++: Общие вопросы > Локальные переменные создаются на стеке... |
| Автор: КунгФуЧайник 5.12.2015, 12:55 |
| Тогда бы, как я понимаю, и в замыканиях смысла не было. Это из-за каких-то аппаратных ограничений? |
| Автор: borisbn 5.12.2015, 13:47 |
| Господа, переведите, пожалуйста, на русский. |
| Автор: КунгФуЧайник 5.12.2015, 16:31 |
| borisbn, не правильно сказал? Вроде же локальные переменные функций создаются в стеке. Хочу понять, почему в стеке, а не в куче. |
| Автор: Фантом 5.12.2015, 19:43 |
| Словосочетание "скорость доступа" ни о чем не говорит? |
| Автор: КунгФуЧайник 5.12.2015, 22:07 |
Это всего лишь словосочетание. Реализовано за счет чего? За счет стековых регистров в процессоре? В них хранятся все локальные переменные? А если переменных много - регистров же мало? |
| Автор: feodorv 6.12.2015, 00:59 |
Да уже простой вызов подпрограммы становится невозможным, так как неизвестно, в каком месте сохранять адрес аллокированного блока локальных переменных самой вызывающей подпрограммы. |
| Автор: math64 6.12.2015, 02:29 |
| Ну, в скриптовых языках память под локальные переменные может располагаться в куче - аппаратных стек используется интерпретатором. Но в обычной, компилируемой программе это не эффективно. Да и то, в стеке как минимум, будут адрес возврата, параметры или указатель на них, (указатель на) локальные переменные. |
| Автор: volatile 6.12.2015, 11:54 | ||
Там всего один стековый регистр, указывающий на вершину стека. Сам стек располагается в памяти. |
| Автор: Alexeis 6.12.2015, 13:56 | ||||
Это детали реализации. Компилятор может зарезервировать для этих указателей фиксированные позиции, например в по отрицательному смещению от точки входа или в любом другом месте, про которое знает компилятор.
Я думаю речь идет об оптимизации переменных в арифметических регистрах. Если подпрограмма небольшая, то для переменных может не понадобиться стек. Сложил несколько регистров и результат выдал в eax. |
| Автор: volatile 6.12.2015, 15:02 | ||||
Если речь идет о таких подпрограммах, тогда топик не имеет смысла
|
| Автор: КунгФуЧайник 6.12.2015, 21:14 | ||||
Понял так: есть Регистры процессора Стек + остальная оперативная память. Стек - та же самая оперативная память, просто структурированная друг-за-другом (читал про стек, push-pop)? Тогда все равно не улавливаю разницы. Почему, например, рекурсия будет не возможна? Ведь что в стеке, что в обычной памяти - все лежит по адресам: запомнил адрес, куда нужно вернуть результат из подпрограммы - подпрограмма выполнилась - результат вернули по адресу. Вроде бы, все тоже самое, что со стеком, но нет "выхода из подпрограммы", в результате которого теряются все локальные переменные этой подпрограммы... Или в этом и разница - как располагается код: друг-за-другом или как попало (читал, в памяти может лежать где угодно - в зависимости, где ему место найдет)? |
| Автор: math64 7.12.2015, 09:34 | ||
Вот структура памяти для ДОС (упрощенная, для винды и линукса немного сложнее, но принцип тот же)
Для выделния памяти в стеке, нужно просто передвинуть SP, при этом размер кучи уменьшается. Для выделния памяти в куче нужно искать свободное место в ней. В старых машинах (ЕС, не помню как назывался их американский прототип фирмы IBM) стека не было. Место под локальные переменные выделялось в сегменте данных, рядом - место для сохранения адреса возврата. В таких условиях рекурсия не возможна - при рекурсивном вызове даже память под адрес возврата будет занята. В микропроцессорах типа 8051 стек есть, но команд, для обращения к нему нет, кроме PUSH и POP. В тоже время оперативной памяти мало, чтобы тратить её как делается в ЕС. Вместо этого компилятор или линковщик строит дерево вызовов и распределяет память с оверлеем. При этом запрещена не только рекурсия, но и вызов функции по указателю. |
| Автор: Alexeis 7.12.2015, 13:09 |
Если мы говорим об оптимизации памяти под замыкания, то предполагается, что локальные переменные для подпрограммы существуют и до входа в подпрограмму и после. Т.е. сохраняют свое состояние. При рекурсии же память под переменные выделяется всякий раз, когда происходит вызов. Т.е. при 10ти вложенностях у нас в стеке 10 копий локальных переменных. Таким образом не соблюдается соотношение, что у каждой подпрограммы свои локальные переменные, которые могли образовать замыкание. Не, ну в теории можно, конечно, выделять память в куче под переменные каждый раз при заходе в подпрограмму, тогда могла бы работать и рекурсия, но эффективность такого подхода была бы чрезвычайно низкой. Так могут работать только интерпретированные языки, но не С++, который ориентирован на максимальную производительность. |