Добрый день. Делаю тестовое задание по С++, возник глюк, объяснения которому не могу найти. Задание (вкратце) такое: Я реализовал. вот так: derevo.h: Код (Text): #define ADDROST 1 #define ADDVOZRAST 1 #define MAXX 1000 #define MAXY 1000 class derevo { char name[256]; int rost; int vozrast; public: int GetRost(); int GetVozrast (); int GetName(char *Name); int SetName(char *Name); void Rosti(); void Copy(derevo newDer); int Srav(derevo SravDer); derevo(); virtual ~derevo(); }; struct derlist { derevo * der; struct derlist * list; }; class les { int x; int y; int count;// счетчик деревьев derevo ** doska; public: int AddDer(); bool DelDer(int x, int y); int GetCount(); bool GetSortList(derevo **list); int GetCountCrug(int x, int y, int radius); derevo* FindDer(char *FindName); les(); virtual ~les(); }; derevo.cpp: Код (Text): #include <stdlib.h> #include <stdio.h> #include <time.h> #include <string.h> #include <math.h> #include "derevo.h" derevo::derevo() { srand( (unsigned)time( NULL ) ); rost = rand()*50/RAND_MAX ; vozrast = rost*7 ; SetName("Elka"); } derevo::~derevo() { } int derevo::GetRost() { return rost; } int derevo::GetVozrast () { return vozrast; } int derevo::GetName(char *Name) { return (int)strcpy(Name, name); } int derevo::SetName(char *Name) { return (int)strcpy(name,Name); } void derevo::Rosti() { rost+=ADDROST; vozrast+=ADDVOZRAST; } void derevo::Copy(derevo newDer) { newDer.SetName(name); newDer.rost = rost; newDer.vozrast = vozrast; } int derevo::Srav(derevo SravDer) { if(SravDer.GetRost()<rost) { return -1; } else { if(SravDer.GetRost()==rost) { return 0; } return 1; } } les::les() { x = MAXX; y = MAXY; doska = (derevo**)calloc(x*y, sizeof(derevo*)); count = 0; } les::~les() { if (doska) { free(doska); } } bool les::DelDer(int x, int y) { if(doska[x,y]!=0) { delete (derevo*)doska[x,y]; doska[x,y]=0; return 1; } else { return 0; } } int les::AddDer() { int x; int y; derevo* Der; Der = new(derevo); srand( (unsigned)time( NULL ) ); x = rand()*MAXX/RAND_MAX ; y = rand()*MAXY/RAND_MAX ; if(doska[x,y]!=0) { AddDer(); } else { doska[x,y]=Der; count++; } return count; } int les::GetCount() { return count; } int les::GetCountCrug(int x, int y, int radius) { int i; int j; int countKrug = 0; for (i=x-radius-1;i<x+radius+1;i++) { for(j=y-radius-1;j<y+radius+1;j++) { if((doska[i,j]!=0)&&(radius>sqrt((x-i)*(x-i)+(y-j)*(y-j)))) { countKrug++; } } } return countKrug; } Вот. Вроде все компилируется без проблем, но при попытке потестировать вот таким кодом: Код (Text): int chislo; les lesss; // lesss = new(les); lesss.AddDer(); lesss.AddDer(); lesss.AddDer(); lesss.AddDer(); chislo = lesss.GetCount(); выскакиевает ошибка 0xc0000005 Access violation, где то в AddDer Если проходить каждую строку медлено в отладчике, то все отрабатывает верно и без глюков, а если поставить бряк на последний AddDer, то выскакивает вот эта ошибка. Что за фигня такая может быть???
Код (Text): int les::AddDer() { //бред поскипан if(doska[x,y]!=0) { AddDer(); } //бред поскипан return count; } Скомпилировал, прогнал. В указанном месте - бесконечная рекурсия. Почему - разбирайся сам. Hint: рекурсия - это очень, очень плохо Ее всегда можно и нужно избегать.
EvilsInterrupt в 99% случаев итерации предпочительней рекурсии в плане скорости и памяти. p.s. 1% исключений бывают, например сортировка Хоара p.s. оптимизированная хвостовая рекурсия не в счет, конечно
Prohvost полезный совет: в рамках одной программы используй один способ работы с динамической памяти. Смешивать стиль С (malloc/free) и C++ (new/delete) очень плохая идея, т.к. можешь запутаться и, к примеру, попытаться освободить память, выделенную malloc'ом через delete, это может плохо кончится.
Это да. Я просто торопился, хотелось написать все за несколько часов, но потом начал путаться. Зря торопился.
Уже понял. Хех, с наскока одолеть не удалось, буду на работе переписывать в свободные минуты все заново.
meduza Вообще-то malloc выделяет память в стеке, а new в Heap, конечно это скорее всего компиляторозависимо, но имхо маленькие и совсем временные блоки лучше malloc, а более менее долгоиграющие new.
Господа, я понимаю, что это форум изначально ассемблеро-ориентированный... Но прежде чем нести подобный бред, хотя бы загляните в стандарт С++. А то ведь молодежь читает это и верит! А потом появляются посты типа "а мне на одном форуме крутые спецы сказали, что типизация в С++ - это для того, чтобы память экономить, а вы тут, лохи, и не знаете!"
Кроме всего этого - однажды родившись дерево не может менять название - логическая, значить, проблемка.