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