Zwracam się do was z prośbą o pomoc w znalezieniu błędu. Duzo już mi pomogliście i wiele się od was nauczyłem za co jestem ogromnie wdzięczny.
Opis Problemu:
Problem jak mniemam, leży w dynamicznym zarządzaniu pamięcią, bardziej po stronie zwalniania niż alokowania, ale głowy nie dam.
W programie jest kilka tablic dynamicznych. Np lista_Studentow w Klasie Dziennik, jest dynamiczna tablica obiektów klasy Student, która to z kolei też posiada dynamiczne tablice.
Szukałem rozwiązania w Symfonii, i wyczytałem aby po zwalnianiu zarezerwowanej pamięci ustawić wskaźniki na NULL, przy ponownej probie usunięcia nie będzie tragedii.
Tak, też zrobiłem ale problem pozostał.
Co zaobserwowałem na testach:
- Przy zakomentowaniu tylko poniższej linijki w main(), program nie wysypuje się
//dziennik.DodajStudenta(s0);
- Przy zakomentowaniu tylko ponizszej linijki w ~Student(), program nie wysypuje się.
//delete[] oceny;
- W konsoli widać, że prze wyjściem z programu Destruktor dla obiektu Student wywołuje się 2 raz, ale nie rozumiem dlaczego.
Błędy:
http://fotowrzut.pl/tmp/upload/KCJS2WOLXY/1.jpg
http://fotowrzut.pl/tmp/upload/YFYA77BMRM/1.jpg
Wybaczcie że, nie wrzucam kodu lecz print screeny, ale myślę, ze lepiej oddaje to istotę problemu, swoją drogą forum ma wylaczone BBCode ?? Nie obsługuje mi miniaturowych obrazków które chciałem umieścić zamiast linków.
Kod Programu:
#include <stdafx.h>
#include <iostream>
#include <cstddef>
using namespace std;
class Student
{
string nazwisko;
int indeks;
int maksOcen; // potrzebujemy ta zmienna aby sprawdzac czy jest mozliwosc dodawania ocen
int *oceny; // tablica dynamiczna zawiera oceny
int obecna_Ilosc_Ocen; // potrzebujemy ta zmienna aby sprawdzac czy jest mozliwosc dodawania ocen
friend class Dziennik; // deklaracja przyjazni z klasa Dziennik, aby dziennik mial dostep do prywatnych skladnikow Studenta. Zyskujemy wiekszy poziom enkapsulacji
public:
// konstruktor z lista inicjalizacyjna i domniemanymi wartosciami
Student(string Nazwisko = "-", int Indeks = 0, int MaksOcen = 3) : nazwisko(Nazwisko), indeks(Indeks), obecna_Ilosc_Ocen(0), maksOcen(MaksOcen)
{
// dynamiczna rezerwacja pamieci
oceny = new int[MaksOcen];
}
~Student()
{
cout << "\nDestruktor Student Poczatek\n";
//zwalniamy dynamiczny przydzial pamieci na tablice
delete[] oceny;
oceny = NULL; // dla bezpieczenstwa po usunieciu ustawiam wskaznik na 0, przy 2 probie usunieciua nie bedzie tragedii
cout << "\nDestruktor Student Koniec \n";
}
};
//******************************************************
class Dziennik
{
static const int zajecia = 15; // liczba zajecia obecnosci, static const wyjatek dla ktorego moge przypsiac w klasie
string kod_Grupy;
int maks_Studentow;
int obecna_ilosc_Studentow;
Student *lista_Studentow; // tablice dynamiczna obiektów klasy student
bool **obecnosci; // dwuwymiarowa tablice dynamiczna bool obecnooci [ilosc_studentow][zajecia] gdzie 15 to liczba zajecia
public:
// Konstruktor z domniemanymi wartosciami i lista inicjalizaycjna
Dziennik(string kod = "s", int ilu_Studentow = 10) : kod_Grupy(kod)
{
obecna_ilosc_Studentow = 0;
maks_Studentow = ilu_Studentow;
// tablica dynamiczna obiektow klasy student
lista_Studentow = new Student[maks_Studentow];
// Dynamiczny przydzial pamieci na tablice 2 wymiarowa, tablica ma meic rozmiar [ilu_Studentow][zajecia]
obecnosci = new bool *[zajecia];
for (int i = 0; i < zajecia; i++)
obecnosci[i] = new bool[ilu_Studentow];
}
// Destruktor
~Dziennik()
{
cout << "\nDestruktor Dziennik Poczatek\n";
// zwalnaimy pamiec, dwuwymiarowej tablicy dynamicznaej bool obecnooci [ilosc_studentow][zajecia]
for (int i = 0; i < maks_Studentow; i++)
{
delete[] obecnosci[i];
obecnosci[i] = NULL; // dla bezpieczenstwa po usunieciu ustawiam wskaznik na 0, przy 2 probie usunieciua nie bedzie tragedii
}
delete[] obecnosci;
obecnosci = NULL; // dla bezpieczenstwa po usunieciu ustawiam wskaznik na 0, przy 2 probie usunieciua nie bedzie tragedii
// zwalniamy pamiec na przydzial dla tablicy dynamicznej obiektow klasy Student
delete[] lista_Studentow;
lista_Studentow = NULL; // dla bezpieczenstwa po usunieciu ustawiam wskaznik na 0, przy 2 probie usunieciua nie bedzie tragedii
cout << "\nDestruktor Dziennik Koniec\n";
}
void DodajStudenta(Student s)
{
if (obecna_ilosc_Studentow < maks_Studentow) // jezeli jeszcze sa miejsca
{
cout << obecna_ilosc_Studentow << " " << maks_Studentow; // TEST
lista_Studentow[obecna_ilosc_Studentow] = s; // dodajemy do listy studenta
obecna_ilosc_Studentow++; // zwiekszamy liczbe studentow
cout << "Student dodany!\n";
}
else
cout << "Nie mozna dodac wiecej studentow dziennik przepelniony!\n";
}
};
int main()
{
// Studenci (nazwisko, indeks, maxymalna liczba ocen)
Student s0("s0", 0, 2);
// Tworzymy dziennik na testy dla 2 studentow
Dziennik dziennik("X", 2);
dziennik.DodajStudenta(s0);
char z;
cout << "Podaj znak aby wyjsc\n";
cin >> z;
return 0;
}
Dziękuję za poświęcony czas
Pozdrawiam!