1). Недоступные блоки — блоки памяти, указатели на которые потеряны.
2). Висящие ссылки — указатели на освобожденные блоки памяти.
3). Повторное освобождение динамической памяти. Недоступные блоки возникают после выделения памяти при присваивании указателю какого — либо другого значения или при уничтожении локального указателя после выхода из области видимости.
Пример 1:
int *a1, *a2;
a1 = new int[1000];//выделили память
… //что-то делаем
a1 = a2; //ошибка — присвоение а1 другого
//значения — память недоступна
Пример 2:
void func(void)
{
int * a1;
a1 = new int[1000];
…
} //ошибка — при выходе из функции автоматически
//уничтожен a1,а память тем не менее осталась
//занята и недоступна.
Необходимо следить за указателями на выделенную память:
int * c;
void func1(void) {
int * a1;
a1 = new int[1000];
c = a1; //если данные по адресу a1 необходимы вне
//func1
… //иначе освободить перед выходом из функции
}
void func2(void)
{
…
delete c;
}
Висящие ссылки возникают при освобождении памяти, на которую указывает более чем 1 указатель:
int *a = new int[1000];
int *a1 = a;
…
delete a;
d = *(a1+50);
//опасно — a1 уже нельзя использовать для обращения к
//массиву!
…
Если нет освобождения памяти, программист в зависимости от конкретной ситуации может посчитать это ошибкой, а может и нет (хотя это в любом случае уменьшает доступные ресурсы памяти), повторное освобождение безусловно ошибочно и скорее всего приведет к зависанию системы. Как правило, подобные ошибки не проявляются немедленно после появления, что затрудняет процесс отладки.