Волгоград Linux User Group |
|
Организована 23 ноября 2002 года
Проект заморожен Птн Июл 6 02:11:14 MSD 2012 |
|
|
Как работает стек?Вопрос: почему это работает?ОтветСтекСтруктура данных «Стек» ведет себя как стопка фарфоровых тарелок. Т.е. ложить и убирать значения можно только сверху. И вверх она растет и уменьшается автоматически по мере добавления новых значений. Вставить дополнительное значение в середину или в самый низ стопки невозможно. Для подобных манипуляций существуют другие структуры данных. Автоматические переменныеВ языке Си есть следующие классы переменных:
Кто где живет:
Правила инициализации значениями таких переменных:
Разбор примераНе будем вдаваться в ужасающие подробности, нас интересуют автоматические переменные. Итак: переменная test это автоматическая переменная, которая содержит указатель на char. Поскольку ее начальное значение не указано, она содержит неопределенное (неинициализированное) значение. Для физической памяти не существует неопределенного состояния поэтому даже в неинициализированной переменной всегда есть Вот пример который может пролить свет на все вышесказанное: Этот код выведет на печать BAR=This is test!. Но не обязательно. Это зависит от реализации. И от компилятора. И от операционной системы. И от фазы луны тоже. Такой код писать нельзя. И доверяться ему нельзя. Мало того, обычно компиляторы ругаются при попытке скомпилировать такой код и говорят что используется неинициализированная переменная. Что же тут произошло? В момент вызова функции f1 была выделена (неинициализированная) память для переменной foo, затем этой переменной было присвоено значение указателя на (динамическую) область памяти которая содержит текст Ahis is test!. Затем выполнение функции f1 завершается, и память занятая переменной foo автоматически освобождается стек укорачивается. Память была освобождена, но значение (указатель на динамически выделенную строку) осталось! Ведь аппаратура памяти не имеет неопределенного состояния для своих ячеек. Поэтому значение там и осталось. Теперь мы снова в функции main и никак не трогая стек тут же вызываем функцию f2. Поскольку стек растет только на вершине, для нее будет повторно выделен тот же участок памяти на стеке что и чуть раньше был выделен функции f1. А там хранится старое значение, которое в нашем случае приобрело новое имя bar, потому что переменная bar не была явно инициализирована другим значением. Мы проводим разные манипуляции с этим значением и даже освобождаем динамическую память, которую занимает неименованное значение (строка) на которое указывает этот указатель. Можно предположить, что компилятор мог бы устанавливать освобождаемую память в определенное заренее значение (которое было бы сигналом об ошибке). Но Функция mainАвтоматические переменные функции main не распологаются у вершины стека. После создания стека загрузчик передает управление той части стандартной библиотеки языка Си, которая подготавливает среду необходимую для работы программы. А этот код также использует стек и оставляет в нем свои мусорные значения. [ |
|
Powered by
|