Использование неинициализированных указателей


При изменении значений указателя не производится никакого контроля за тем, чтобы новый адрес памяти был легально выделен программе. Так, записав последовательность операторов

int *pv = new int;

pv++;

*pv=1;

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

При записи выражений с указателями следует обращать внимание на приоритет операций и при необходимости расставлять скобки. Так, выражение (*p)++ увеличивает значение, расположенное по адресу, хранящемуся в p. С другой стороны, выражение *(p++) изменяет значение указателя. Тем не менее, оба выражения возвращают старые данные, хранящиеся по старому адресу. Поэтому, записывая оператор *p++, задумайтесь – поймет ли компилятор то, что вы хотели сказать!

(*p++выполняется в C++ как *(p++))

Константные указатели

В C++ они подразделяются на два типа:

- указатели, значение которых не изменяется в ходе выполнения программы. Они описываются, например, так:

int a;

int * const p=&a;

В этом случае значение p не может быть изменено, и операторp++вызовет ошибку;

- указатели, хранящие адрес константы. Они описываются следующим образом:

int a;

const int *p=&a;

В этом случае ошибку компиляции вызовет оператор (*p)++.

С другой стороны, оператор a++ считается вполне нормальным.

Динамическое выделение памяти
Выделение динамической памяти для переменной типа int можно выполнить двумя способами:
a) с помощью функции malloc, описанной еще в языке C:
int *pi=(int*)malloc(sizeof(int));
(функция malloc возвращает значение типа
void *, и необходимо выполнить преобразование типа)
b) с помощью появившейся в C++ операции new:
int *pi = new int;
Освобождение памяти соответственно:
free(pi);
delete pi;

После освобождения памяти значение указателя не изменяется!!!

Проблемы, возникающие при работе с указателями

Неинициализированный указатель содержит какое-то значение, которое трактуется как адрес памяти. Если случайно окажется, что этот адрес доступен для приложения – последствия непредсказуемы!

2. Использование “зависших” указателей

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

3. “Утечка” памяти

Потеря значения адреса выделенной памяти влечет невозможность доступа к ней (в том числе и освобождения) до окончания работы программы.