Witam społeczność, niestety od razu z problemem.
Piszę program mający imitować w pewien sposób dziennik szkolny. Od kilku dni zmagam się z potężnym problemem związanym z dynamiczną alokacją i zwalnianiem pamięci.
Może najpierw fragmenty kodu, w których prawdopodobnie leży problem.
Napis.h
class Napis
{
char *imie;
char *nazwisko;
public:
Napis();
Napis(const char *i, const char *n);
Napis(const Napis& wzor);
void Zmien_Imie(const char* nowe_imie);
void Zmien_Nazwisko(const char* nowe_nazwisko);
~Napis();
};
Napis.cpp
Napis::Napis()
{
imie = new char[30];
nazwisko = new char[30];
}
Napis::Napis(const char *i, const char *n)
{
imie = new char[30];
nazwisko = new char[30];
strncpy(imie, i, strlen(i)+1);
strncpy(nazwisko, n, strlen(n)+1);
}
Napis::Napis(const Napis& wzor)
{
imie = new char[30];
nazwisko = new char[30];
strncpy(imie, wzor.imie, strlen(wzor.imie) + 1);
strncpy(nazwisko, wzor.nazwisko, strlen(wzor.nazwisko) + 1);
}
void Napis::Zmien_Imie(const char* nowe_imie)
{
delete[] imie;
imie = new char[strlen(nowe_imie) + 1];
strcpy(imie, nowe_imie);
}
void Napis::Zmien_Nazwisko(const char* nowe_nazwisko)
{
delete[] nazwisko;
nazwisko = new char[strlen(nowe_nazwisko) + 1];
strcpy(nazwisko, nowe_nazwisko);
}
Napis::~Napis()
{
delete[] imie;
delete[] nazwisko;
}
main.cpp
int main()
{
vector <Napis> wek;
for (int i = 0; i < 20; i++)
{
Napis a("Imie", "Nazwisko");
a.Zmien_Imie("Nowe_Imie");
a.Zmien_Nazwisko("Nowe_Nazwisko");
wek.insert(wek.begin(), a);
cout << "i = " << i << endl << endl;
}
system("PAUSE");
}
Ograniczyłem krąg poszukiwań do tych fragmentów kodu głównego projektu. Mają one symulować działanie tej części programu (mam całą funkcję losującą uczniów i dodającą ich w odpowiednim miejscu do wektora) i prawie na pewno tutaj gdzieś występuje błąd.
Jaki? Mianowicie, od szóstej iteracji zaczynają się dziać jakieś dziwne rzeczy, po których zawartość wektora pod zerowym indeksem się zwalnia i w jej miejsce pojawiają się krzaki z pamięci. W rezultacie, kilka iteracji dalej, program się wysypuje próbując zwolnić zwolnioną pamięć (słynny błąd 'triggered a breakpoint").
Rozumiem, że ma to jakiś związek ze specyfiką tego kontenera, który przy dodawaniu elementu na początek musi sam realokować pamięć, sam przesuwać wszystkie elementy i sam je wówczas zwalniać. Nie rozumiem tylko dlaczego pomimo poprawnych (domniemując) konstruktorów oraz destruktora, dzieją się takie cuda. Ale w takim razie dlaczego nie dzieje się to przy dodawaniu np. drugiego albo trzeciego elementu (przecież wtedy także pamięć po elementach jest zwalniana przy przesuwaniu), ale dopiero od szóstego?
Problem nie występuje, gdy użyję funkcji push_back lub wek.end() jako argument do 'insert', ale to jest w pewnym sensie zrozumiałe, ponieważ żadne elementy się wówczas nie przesuwają w wektorze. Gdy zakomentuję linie destruktora problem także znika, co również jest dość oczywiste w przypadku błędu dwukrotnego zwalniania tego samego obszaru pamięci, ale to z kolei generuje wycieki, które raczej nie są mile widziane.
Jeśli to ma w czymś pomóc, w głównym projekcie wektor ma reprezentować klasę uczniów i być złożony właśnie z obiektów klasy 'Uczen', które z kolei jako jedno z pól składowych przyjmują obiekt klasy 'Napis'. Pierwotny plan zakładał alokowanie całej klasy uczniów ręcznie. Gdy to zawiodło, przestawiłem się na wektory z myślą, że coś to pomoże. Niestety niewiele dało, bo błąd jest identyczny. Stąd poszukiwania dotarły aż do klasy 'Napis'.
Z góry dziękuję za wszelkie sugestie.
Pozdrawiam serdecznie :)