Ошибки при использовании динамичской памяти

Инициализаторы с операцией new

Операция new с массивами

Если "имя" это массив, то возвращаемый new указатель указывает на первый элемент массива. При создании с помощью new многомерных массивов следует указывать все размерности массива:

mat_ptr = new int[3][10][12]; // так можно

mat_ptr = new int[3][][12]; // нельзя

...

delete [] mat_ptr; //освободить память, занятую массивом,

//на который указывает mat_ptr

Другим преимуществом операции new по сравнению с malloc является возможность инициализации. При отсутствии явных инициализаторов объект, создаваемый new, содержит непредсказуемые данные ("мусор"). Объекты, распределяемые new, за исключением массивов, могут инициализироваться соответствующим выражением в скобках:

int_ptr = new int(3);

Для очистки выделенной памяти операцией new можно использовать функцию meset(), объявленную в <mem.h>. Ей передаются 3 параметра: адрес очищаемой памяти, символ для очистки, количество байт.

#include <string.h>

#include <stdio.h>

#include <mem.h>

int main(void) {

char buffer[] = "Hello world\n";

printf("Буфер до memset: %s\n", buffer);

memset(buffer, '*', strlen(buffer) - 1);

printf("Буфер после memset: %s\n", buffer);

return 0;

}

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 уже нельзя использовать для обращения к

//массиву!

...

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

Написать программу учета успеваемости группы. Программа должна считать ср. бал группы и выводить на экран.

#include <stdio.h>

#include <conio.h>

#include <iostream.h>

void main(void) {

int i,j,n;

float varsum=0;

struct stud { char fio[15]; char name[10];

struct exam { int val1; int val2;

int val3; int val4;}estimate;

float midle;

};

puts(«введите кол-во студентов”);

cin>>n;

struct stud *pgroup=new struct stud[n];

for(i=0; i<n; i++) {

printf(“Введите данные по %d студенту\n”,i+1);

cout<< “Фамилия:”;

gets(pgroup->fio);

cout<< “Имя:”;

gets(pgroup->name);

cout<< “Оценка за 1-й экзамен:”;

gets(pgroup->estimate.val1);

cout<< “Оценка за 2-й экзамен:”;

gets(pgroup->estimate.val2);

cout<< “Оценка за 3-й экзамен:”;

gets(pgroup->estimate.val3);

cout<< “Оценка за 4-й экзамен:”;

gets(pgroup->estimate.val4);

pgroup->middle = (pgroup->estimate.val1+pgroup->estimate.val2+ pgroup->estimate.val3+ pgroup->estimate.val4)/4;

cout<<”Средний бал ”<< pgroup->fio<< pgroup->name<< pgroup->midle<<endl;

varsum+= pgroup->midle;

}

cout<<»Средний балл по группе”<<varsum/n<<endl;

delete[] pgroup;

}


Понравилась статья? Добавь ее в закладку (CTRL+D) и не забудь поделиться с друзьями:  



double arrow
Сейчас читают про: