- •Краткие теоретические сведения
- •1.1.1Логическая структура памяти программы
- •1.1.2 Указатели. Типизированные указатели.
- •1.1.4Состояния указателей
- •1.2 Примеры работы с указателями
- •1.2.1Два указателя содержат адрес одной и той же переменной
- •1.2.2Ситуация утечки памяти
- •1.3 Задания для самопроверки
- •1.4 Создание проекта
- •1.5 Проведение исследований по использованию типизированных указателей в программе
- •1.3 Содержание отчета
- •Контрольные вопросы и задания
1.1.4Состояния указателей
Указатели могут иметь 3 состояния:
Инициированный указатель. Указатель, указывающий на какие-то данные.
Пустой указатель. Указатель, содержащий пустое значение – NULL.
Мусорный указатель. Очень опасный тип указателя. Он содержит какое-то значение, но не указывает никуда. Указатель оказывается в таком состоянии сразу после объявления и после того как память, на которую он указывает, уже освободили. Ошибки, основанные на попытках использования мусорных указателей, доставляют больше всего хлопот. Поэтому рекомендуется своевременно устанавливать неиспользуемым указателям значение NULL и проверять их при использовании на это значение.
1.2 Примеры работы с указателями
1.2.1Два указателя содержат адрес одной и той же переменной
Ситуация, когда два указателя содержат адрес одной и той же переменной может быть изображена на рисунке 1.18.
Статическая память
P1
P2
34567
34567
|
Динамическая память
|
Рисунок 1.18 – Ситуация, когда два указателя содержат адрес одной и той же переменной
Для создания вышеописанной ситуации может быть выполнена программа, показанная на рисунке 1.19.
Следует обратить внимание на то, что на рисунке 1.18 изображена только одна динамическая переменная. Следовательно, только один раз в программе будет вызван оператор New.
{ int *p1, *p2 ; //объявляем переменные – типизированные указатели // p1, p2 – в них «мусор»
// Пока еще в памяти нет динамической переменной // Теперь вызываем оператор new для запроса памяти для динамической // переменной
p1 = new int;
// Теперь в динамической памяти появилась переменная типа integer // и переменная-указатель p1 содержит ее адрес (см.Рисунок 1.18)
// Заносим в переменную в динамической памяти значение 36, путем // разыменования указателя p1
*p1 = 36;
// Теперь необходимо в переменную p2 занести такое же значение, как // в p1. Это две статические переменные. Путем присваивания копируем //значение одной переменной в другую. Они однотипные переменные.
p1 = p2;
} |
Рисунок 1.19 – Программа, выполнение которой приведет к размещению данных в памяти, соответствующему рисунку 1.18
1.2.2Ситуация утечки памяти
Ситуация, когда в динамической памяти находится занятый участок и ни один из имеющихся указателей не содержит его адрес, называется утечкой памяти. К такому участку памяти уже не возможно получить доступ, его невозможно освободить до окончания работы программы и самое плохое – он занимает место, которое не может быть выделено другой переменной.
Утечка памяти возникает тогда, когда программист забывает освобождать память перед тем, как указатель получает адрес другого участка памяти.
Такая ситуация изображена на рисунке 1.20.
Статическая память
P1
34567
|
Динамическая память
|
Рисунок 1.20 – Ситуация утечки памяти
Для создания вышеописанной ситуации может быть выполнена программа, показанная на рисунке 1.21.
Следует обратить внимание на то, что на рисунке 1.20 изображено две динамические переменные. Следовательно, в программе будет вызван оператор new дважды.
{ int *p1; //объявляем переменную – типизированный указатель // p12 – в ней «мусор»
// Пока еще в памяти нет динамической переменной // Теперь вызываем оператор new для запроса памяти для динамической // переменной
p1 = new int;
// Теперь в динамической памяти появилась переменная типа integer // и переменная-указатель p1 содержит ее адрес (см.Рисунок 1.18)
// Вызываем еще раз процедуру new, в результате чего p1 получит адрес // вновь выделенного участка памяти, а предыдущий участок будет // потерян
p1 = new int;
//Возникла утечка памяти
} |
Рисунок 1.21 – Пример программы, выполнение которой приведет к утечке памяти
