Типичные ошибки при работе с динамической памятью

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

1) Попытка воспользоваться неинициализированным указателем.

float *pi;

*pi=3.14;//использование неинициализированного указателя

Если pi – глобальная переменная, то она автоматически инициализируется нулевым значением, т.е. имеет значение NULL. Разыменование нулевого указателя приводит к ошибке времени выполнения. Если pi – локальная переменная, то она по умолчанию не инициализируется, а поэтому содержит непредсказуемое значение. Это значение трактуется как адрес вещественной переменной, к которой осуществляется доступ. По чистой случайности может оказаться, что указатель pi содержит истинный адрес переменной программы, тогда значение переменной будет изменено, выполнение программы продолжится дальше, а факт изменения переменной непредсказуемым образом повлияет на дальнейшее выполнение программы.

2) «Висячие» указатели.

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

int *p;

p= new int;

*p=55;

delete p; // указатель становится «висячим»

*p=8; // использование «висячего» указателя

Если после delete p; сразу написать p=NULL;, то в дальнейшем при попытке разыменовать нулевой указатель p возникнет исключение, что является более предпочтительным, чем скрытая ошибка изменения другой переменной. Данный прием следует иметь ввиду и после освобождения динамической переменной обнулять указатель:

delete p;

p=NULL;

3) «Утечка» памяти.

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

Пример. Повторное выделение памяти.

Если выделить память повторно для того же указателя, то ранее выделенная память «утечет»:

int *p;

p= new int;

*p=55;

p= new int;

//выделяется новый участок памяти под тот же указатель

Пример. Выделение памяти под локальную переменную без освобождения.

function pp (int n) {

int *p;

p= new int;

*p=n;

}

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

4) Попытка освободить динамическую память, не выделенную ранее.

int *p;

delete p;

Вызов операции delete для неинициализированного указателя игнорируется, не приводя к генерации ошибки.

5) Попытка освободить нединамическую память.

int *p,i=55;

p=&i;

delete p;

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

 








Дата добавления: 2015-02-16; просмотров: 1547;


Поиск по сайту:

При помощи поиска вы сможете найти нужную вам информацию.

Поделитесь с друзьями:

Если вам перенёс пользу информационный материал, или помог в учебе – поделитесь этим сайтом с друзьями и знакомыми.
helpiks.org - Хелпикс.Орг - 2014-2024 год. Материал сайта представляется для ознакомительного и учебного использования. | Поддержка
Генерация страницы за: 0.009 сек.