Ошибки при использовании динамичской памяти
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; }
ФАЙЛ
Язык Си "рассматривает" файл как структуру. В stadio.h содержится определение структуры файла. Определен шаблон и директива препроцессора #defile FILE struct iobuf FILEкраткое наименование шаблона файла. Некоторые системы используют директиву typedef для установления этого соответствия. typedef struct iobuf FILE
Открытие файла fopen()
Функцией управляют три параметра. FILE *in; //указатель потока Для связывания указателя с файлом служит функция открытия файла fopen(), которая объявлена в заголовочном файле <stdio.h>. in = fopen("test", "r"); 1 параметр - имя открываемого файла 2 параметр - "r"-по чтению "r+"-чтение и запись "w"-по записи "w+"-запись и чтение, если файл уже был, он перезаписываетя "a"-дозапись "a+"-чтение и дозапись, если файла еще не было, он создается "b"-двоичный файл "t"-текстовый файл in является указателем на файл "test". Теперь будем обращаться к файлу через этот указатель. Если файл не был открыт (его нет, нет места на диске), то возвращается в указатель 0. if((in=fopen("test", "r"))==0) puts("Ошибка открытия файла"); Можно по другому in=fopen("test", "r"); if (!in) puts("Ошибка открытия файла");
Закрытие файла fclose()
fclose(FILE *stream); //Если файл закрыт успешно, то возвращается 0 иначе -1.
Функции ввода/вывода одного символа fgetc(), fputc()
1. Чтение из файла посимвольно int fgetc(FILE *stream);
2. Запись в файл посимвольно int fputc(int c, FILE *stream); Код этого же символа и возвращается.
ch=fgetc(in); fputc(ch,out);
# include <stadio.h> void main(void){ FILE *in,*out; char ch; if((in=fopen("prog1", "r"))==0) fputs("Ошибка открытия prog1"); if((out=fopen("prog2", "w"))==0) fputs("Ошибка открытия prog2); while((ch=getc(in))!=EOF) //”End Оf File” константа определенная в dos.h fputc(ch, out); fclose(in); fclose(out); }
Функции форматированного ввода/вывода в файл
1. Форматированный вывод в текстовый файл int fprintf(FILE *stream,”управл.cтрока”,arg1,…) Возвращает количество записанных байтов.
2. Форматированный ввод из текстового файла int fscanf(FILE *stream,”управл.cтрока”,&arg1,…) Возвращает количество прочитанных байтов.
# include<stadio.h> void main(void){ FILE*in; int age; in=fopen("prog1", "r"); fscanf(in,"%d",&age); fclose(in); in=fopen("prog2", "w"); fprintf(in,"число %d\n",age); fclose(in); } Модификаторы и спецификаторы, те же, что и в printf().
Популярное: Почему стероиды повышают давление?: Основных причин три... Организация как механизм и форма жизни коллектива: Организация не сможет достичь поставленных целей без соответствующей внутренней... ©2015-2024 megaobuchalka.ru Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. (326)
|
Почему 1285321 студент выбрали МегаОбучалку... Система поиска информации Мобильная версия сайта Удобная навигация Нет шокирующей рекламы |