Std::cout << b << std::endl; // выведет 3
}
Сегмент стека (stack segment), также называемый автоматической памятью, содержит локальные переменные и аргументы функций. Также при вызовах функций здесь размещается служебная информация, такая как состояние регистров процессора до вызова для последующего восстановления, адрес инструкции в сегменте кода для возврата после завершения работы вызванной функции, адрес переменной-результата для больших объектов и др. Стек заполняется снизу вверх по мере необходимости, в зависимости от характера вызовов функций и содержащихся в них переменных и связанных служебных данных. При выходе из функции задействованная ей память в стеке считается свободной и может быть использована другими функциями.
Ниже представлено содержимое стека в 3 момента времени, соответствующие состояниям до вызова функции f, внутри его и после возврата в функцию main:
voidf ( intx )
{
inty = x + 4; // Точка 2
// ...
}
intmain ()
{
int a = 5; // Точка 1
f( 3 );
// Точка 3
}
Служебная информация о вызове: адрес возврата, сохраненные регистры ... |
Переменная а в функции main |
1) |
2) |
Вершина |
? |
Вершина |
Переменная а в функции main |
Аргумент функции |
Переменная y в функции f |
3) |
? |
Вершина |
Переменная а в функции main |
Уже свободная часть стека, будет затерта в любой момент |
В отличие от сегмента кода и сегмента данных, точный необходимый размер для стека вычислить во время компиляции не представляется возможным, т.к. функции могут вызывать друг друга с очень большим и непредсказуемым уровнем вложенности. Соответственно, выделяется некоторый конечный достаточно большой для общего назначения размер. Этот размер зависит от используемого компилятора и может быть настроен в случае необходимости. Программы в среде Visual Studio по умолчанию получают стек размером 1 мегабайт. Достичь данного предела не так уж сложно, достаточно объявить внутри функции слишком большой по размеру массив:
intmain ()
{
charbuf[ 2000000 ];
buf[ 0 ] = 'a';
}
Запуск такой программы приведет к ошибке переполнения стека:
Из этого вытекает, что стек не предназначен для хранения больших объемов данных, а должен использоваться лишь для промежуточных переменных и аргументов функций.
Переполнение стека также может случиться из-за слишком глубокого уровня вложенности вызовов функций. Это легко продемонстрировать на приведенной ниже некорректной рекурсивной функции. Хотя функция и не содержит ни одного локальной переменной и ни одного аргумента, объем сохраняемой служебной информации через некоторое время превысит ограничение на размер стека:
intf ()
{
Дата добавления: 2016-01-29; просмотров: 686;