Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
СТА (лекции+лабы) / СТА Лекция 1.docx
Скачиваний:
51
Добавлен:
16.03.2016
Размер:
336.41 Кб
Скачать

Int main ()

{

inta = 5;// Точка 1

f( 3 );

// Точка 3

}

В отличие от сегмента кода и сегмента данных, точный необходимый размер для стека вычислить во время компиляции не представляется возможным, т.к. функции могут вызывать друг друга с очень большим и непредсказуемым уровнем вложенности. Соответственно, выделяется некоторый конечный достаточно большой для общего назначения размер. Этот размер зависит от используемого компилятора и может быть настроен в случае необходимости. Программы в среде Visual Studio по умолчанию получают стек размером 1 мегабайт. Достичь данного предела не так уж сложно, достаточно объявить внутри функции слишком большой по размеру массив:

Int main ()

{

Char buf[ 2000000 ];

buf[ 0 ] = 'a';

}

Запуск такой программы приведет к ошибке переполнения стека:

Из этого вытекает, что стек не предназначен для хранения больших объемов данных, а должен использоваться лишь для промежуточных переменных и аргументов функций.

Переполнение стека также может случиться из-за слишком глубокого уровня вложенности вызовов функций. Это легко продемонстрировать на приведенной ниже некорректной рекурсивной функции. Хотя функция и не содержит ни одного локальной переменной и ни одного аргумента, объем сохраняемой служебной информации через некоторое время превысит ограничение на размер стека:

int f ()

{

Return f();// бесконечно долго вызываем сами себя // вызываем переполнение стека через время

}

Int main ()

{

Return f();

}

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

Вся остальная наибольшая область памяти называется кучей (heap), или динамической памятью, и распределяется программистом вручную при помощи операторовnew. В отличие от других областей памяти, освобождение блоков в динамической памяти также нужно делать вручную, используя операторыdelete. Например, следующая программа выделяет блок памяти из 10 миллионов целых чисел, а затем освобождает его:

Int main ()

{

int * p =new int[ 10000000 ];// Выделяем память

Delete[]p;// Освобождаем память

}

Если при помощи new выделялся массив, то освобождать его нужно при помощи оператораdelete[]. Если выделялся одиночный объект - его освобождают через операторdelete. В ряде сред разработки нарушение данного правила приводит к фатальному завершению программы (к сожалению, Visual Studio о такой ошибке никак не сигнализирует).

Наиболее важное преимущество динамической памяти - возможность определения объема выделения во время выполнения программы. Выделяя массивы в глобальной области либо на стеке необходимо указывать их конкретные исчисляемые во время компиляции размеры. При выделении же массивов в динамической памяти, их размер может определяться значением любого выражения с переменными, зависящего от текущего состояния программы, внешних данных от пользователя и других факторов.

#include<iostream>

Соседние файлы в папке СТА (лекции+лабы)