Wycieki pamięci (potencjalne).

0

Obawiam się, że ryzyko wycieków pamięci w tak napisanym programie jest dość znaczne.
Jak mogę zmodyfikować program, by takie ryzyko ograniczyć i jak upewnić się, że wycieków brak?

Jeżeli komuś chciałoby się rzucić okiem:
(chetnie wyslucham rowniez jakichkolwiek innych uwag dotyczacych kodu)

Student.h

 
#pragma once
#include <iostream>
#include <fstream>
#include <vector>
#include <string>

using namespace std;

class CStudent;

ostream& operator<< (ostream& out, const CStudent& Student);   //przeciazenie operatora wyjscia
fstream& operator<< (fstream& file, const CStudent& Student);

class CStudent
{
public:
	CStudent();
	~CStudent();

	static void CreateStudents();
	static void SetNrStudents(int nrStudents);
	static void AddStudents(int addStudents = 1);
	static void DeleteStudent(int deleteStudent);
	static void Menu();
	static void ShowDane();
	static void SaveDane();
	static void DeleteIt();

	friend ostream& operator<< (ostream& out, const CStudent& Student);   // zaprzyjaznienie przeciazonego operatora
	friend fstream& operator<< (fstream& file, const CStudent& Student);

private:	
	void SetDane();

	static vector <CStudent*> _students;
	static int _nrStudents;
	
	string _imie;
	string _nazwisko;
	int _nrAlbumu;
	float _srednia;
	string* _przedmioty;
	int _nrPrzedmioty;
};

Student.cpp

 #include "Student.h"

CStudent::CStudent()
{
	cout << endl << "###  KONSTRUKTOR" << endl;   // Just for info
	SetDane();
}


CStudent::~CStudent()
{
	if (_przedmioty != NULL)
	{
		delete[] _przedmioty;
		_przedmioty = NULL;
	}
	cout << endl << "---  DESTRUKT" << endl;    // Just for info
}

void CStudent::SetNrStudents(int nrStudents)    
{
	_nrStudents = nrStudents;
}

void CStudent::Menu()
{
	cout << endl << "MENU" << endl;
	cout << "################" << endl;
	cout << "0. Usun i zakoncz" << endl;
	cout << "1. Dodaj Studenta" << endl;
	cout << "2. Usun Studenta" << endl;
	cout << "3. Pokaz Baze" << endl;
	cout << "4. Zapisz do pliku" << endl;
}

void CStudent::CreateStudents()
{
	for (int i = 0; i < _nrStudents; i++)
	{
		_students.push_back(new CStudent());   // Utworzenie nowego obiektu w "vektorze"
	}
}

void CStudent::AddStudents(int addStudents)
{
	for (int i = 0; i < addStudents; i++)
	{
		_students.push_back(new CStudent());   // Utworzenie nowego obiektu
	}
	_nrStudents += addStudents;
}

void CStudent::DeleteStudent(int deleteStudent)
{	
	delete *(CStudent::_students.begin() + deleteStudent);			// Usuwanie obiektu
	*(CStudent::_students.begin() + deleteStudent) = NULL;			// "zerowanie" wskaznika
	_students.erase(CStudent::_students.begin() + deleteStudent);   // usuwanie elementu z "vektora"
	_nrStudents--;
}

void CStudent::SetDane()
{
	cout << endl << "Imie: " << endl;
	cin >> _imie;
	cout << endl << "Nazwisko: " << endl;
	cin >> _nazwisko;
	cout << endl << "Numer Albumu: " << endl;
	cin >> _nrAlbumu;
	cout << endl << "Srednia: " << endl;
	cin >> _srednia;
	cout << endl << "Podaj ilosc przedmiotow: " << endl;
	cin >> _nrPrzedmioty;
	_przedmioty = new string[_nrPrzedmioty];  // Dynamiczna alokacja
	for (int i = 0; i < _nrPrzedmioty; i++)
	{
		cout << endl << "Nazwa przedmiotu nr: " << (i + 1) << " z " << _nrPrzedmioty << endl;
		cin >> _przedmioty[i];
	}
	cout << endl << "Wczytano studenta z liczba przedmiotow: " << _nrPrzedmioty << endl;
}

void CStudent::ShowDane()
{
	int c = 0;
	vector<CStudent*>::iterator itr;  // iterator do sprawnego poruszania sie po elementach vektora
	for (itr = CStudent::_students.begin(); itr != CStudent::_students.end(); itr++)
	{
		cout << endl << "Student nr: " << c << endl;
		cout << **itr;
		c++;
	}
}

void CStudent::SaveDane()
{
	int c = 0;
	fstream file("student.txt", ios::out);
	vector<CStudent*>::iterator itr;
	for (itr = CStudent::_students.begin(); itr != CStudent::_students.end(); itr++)
	{
		file << endl << "Student nr: " << c << endl;
		file << **itr;
		c++;
	}
	file.close();
}

void CStudent::DeleteIt()   // Usuwanie dynamicznie zaalokowan pamiecie, czyszczenie vektora
{
	vector<CStudent*>::iterator itr;
	for (int i = 0; (CStudent::_students.begin() + i) != CStudent::_students.end(); i++)
	{
		CStudent::_students.begin();
		delete *(CStudent::_students.begin() + i);
		*(CStudent::_students.begin() + i) = NULL;
	}
	_students.clear();
}

vector <CStudent*> CStudent::_students;   // inicjalizacja pola statyczneg0
int CStudent::_nrStudents = 0;			  // -||-

ostream& operator<< (ostream& out, const CStudent& Student)
{
	out << "------------------" << endl;
	out << Student._imie << endl << Student._nazwisko << endl << Student._nrAlbumu << endl << Student._srednia << endl;
	out << "Przedmioty: " << endl;
	for (int i = 0; i < Student._nrPrzedmioty; i++)
	{
		out << Student._przedmioty[i] << endl;
	}
	return out;
}

fstream& operator<< (fstream& file, const CStudent& Student)
{
	file << "------------------" << endl;
	file << Student._imie << endl << Student._nazwisko << endl << hex << Student._nrAlbumu << endl << Student._srednia << endl;
	file << "Przedmioty: " << endl;
	for (int i = 0; i < Student._nrPrzedmioty; i++)
	{
		file << Student._przedmioty[i] << endl;
	}
	return file;
}

main.cpp

 #include "Student.h"

int main(void)
{
	int choice;
	int nrS;
	cout << "Ilu studentow?" << endl;
	cin >> nrS;
	CStudent::SetNrStudents(nrS);  // Utworzenie poczatkowo podanej ilosci studentow
	CStudent::CreateStudents();

	do
	{
		CStudent::Menu();
		cin >> choice;
		switch (choice)
		{
		case 1:
			int ile;
			cout << endl << "Ilu studentow dodac?" << endl;
			cin >> ile;
			CStudent::AddStudents(ile);
			break;
			
		case 2:
			int ktory;
			cout << endl << "Ktorego usunac?" << endl;
			cin >> ktory;
			CStudent::DeleteStudent(ktory);
			break;

		case 3:
			CStudent::ShowDane();
			break;

		case 4:
			CStudent::SaveDane();
			break;

		case 0:
			CStudent::DeleteIt();
			break;

		}
		
	} while (choice != 0);

	return 0;
}

btw. istnieje opcja typu 'spojler' ? (w celu ukrycia przydługiego tekstu).

3

Nie używaj nagich wskaźników do oznaczenia właściciela. Nie używaj nagiego new i delete. Używaj dobrodziejstw C++ - kontenerów, mądrych wskaźników i RAII.

3
  1. Nie używasz polimorfii? Nie alokuj nic na swoją rękę
  2. Chcesz mieć zbiór czegoś? Użyj kontenerów z biblioteki standardowej, np std::vector
  3. Nie używaj nagiego new/delete

1 użytkowników online, w tym zalogowanych: 0, gości: 1