2013-11-01 8 views
2

Я читал [1] о указателях стека и необходимости знать как ebp (начало стека для функции), так и esp (end). В статье говорилось, что вам нужно знать, потому что стек может расти, но я не вижу, как это возможно в c/C++. (Я не говорю о вызове другой функции, потому что, на мой взгляд, это будет увеличивать стек, делать какие-то вещи, а затем рекурсивно выскакивать и возвращаться к состоянию перед вызовом).c/C++ allocate on stack

Я проделал немного исследований и видел только людей говоря, что new выделяет кучу. Но указатель будет локальной переменной, не так ли? И это известно во время компиляции и зарезервировано в стеке во время вызова функции.

Я начал думать, что, возможно, с петлями у вас есть неконтролируемое количество локальных переменных

int a; 
for (int i = 0; i < n; ++i) 
    int b = i + 3; 

но нет, это не выделяет п раз b, и только 1 INT зарезервирован так же, как это для a.

Итак ... любой пример?

[1): http://en.wikibooks.org/wiki/X86_Disassembly/Functions_and_Stack_Frames

+0

Все переменные в C и C++ существуют в контексте * scope *. Например, локальные нестатические переменные в функции являются автоматическими только для этой функции. Тем не менее, что, по вашему мнению, имеет смысл существования 'b' в вашем коде? – WhozCraig

+0

Нет ничего «неконтролируемого» в вашем примере с точки зрения компилятора. –

+0

Где в статье говорится: «Вам нужно знать, потому что стек может расти»?Он говорит только о параметрах, передаваемых в стек. – delnan

ответ

5

Вы можете выделить память в стеке с помощью функции alloca из stdlib. Я не рекомендую использовать эту функцию в производственном коде. Это легко повредить ваш стек или получить переполнение стека.

+0

C99 добавила поддержку массивов переменной длины, которые также распределены таким образом. 'int foo (unsigned sz) {char bar [sz]; ... ' – nategoose

0

Указатель действительно выделяется в стеке. И размер обычно составляет 4 или 8 байт на 32 и 64-битных архитектурах соответственно. Таким образом, вы знаете размер указателя статически, во время компиляции, и можете сохранить их в стеке, если вы решите это сделать.

Этот указатель может указывать на бесплатное хранилище, и вы можете распределять память на нем динамически - без предварительного уведомления о размере. Кроме того, обычно рекомендуется сохранять пустые стеки, а компиляторы даже «применяют» это с (регулируемыми) пределами. Если я правильно помню, MSVC имеет 1 МБ.

Нет, вы не можете создать фрейм стека размера, который неизвестен во время компиляции. Ваш стек стека кода, который вы отправили, будет содержать 3 целых числа (a, b, i). (И, возможно, некоторая прокладка, теневое пространство и т. Д., Не имеет значения.) (ТЕХНИЧЕСКОЙ можно увеличить размер стековых кадров во время выполнения, но вы просто не хотите этого почти никогда не делать.)

1

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

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

Единственный способ, которым я знаю, что время нарастать в неопределенном виде во время компиляции, - это использовать alloca повторно.

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