Serdecznie dziękuje za pomoc! wszystko działa :)
Nie działa.
Masz tam wielkiego, brzydkiego i paskudnie trudnego w debuggowaniu memleaka.
Spójrz:
#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <vector>
using namespace std;
int allocs = 0;
class Foo {
public:
void* operator new(size_t sz) {
if(rand() % 2 == 0)
throw bad_alloc();
void* storage = malloc(sz);
allocs += 1;
return storage;
}
void operator delete(void* ptr) {
allocs -= 1;
free(ptr);
}
};
class ExtremelyBadClass {
public:
ExtremelyBadClass() {
f1 = new Foo();
f2 = new Foo();
}
~ExtremelyBadClass() {
if(f1 != nullptr) delete f1;
if(f2 != nullptr) delete f2;
}
private:
Foo *f1, *f2;
};
int main() {
srand(time(nullptr));
vector<ExtremelyBadClass*> v;
for(size_t i = 0; i < 1000; ++i) {
try {
v.push_back(new ExtremelyBadClass());
}
catch(exception e) {
}
}
for(auto obj : v) delete obj;
printf("%d\n", allocs);
return 0;
}
Dlaczego tak się dzieje?
#Jeśli drugie new
rzuci wyjątek, pierwszy obiekt nie jest czyszczony (mimo, że zaalokowaliśmy mu miejsce na stercie).
#Pierwszy obiekt nie jest czyszczony ponieważ nie udało się stworzyć klasy przechowującej te wskaźniki.
#Nie wywołuję się destruktor bo żaden z konstruktorów nie został wykonany od początku do końca.
Możliwe rozwiązania.
#Nie trzymać więcej niż jednego pointera w klasie.
#Dodać konstruktor przypisujący nullptr
obu wskaźnikom i wywołać go w drugim konstruktorze (przypisującym wartości).
#Używać smart pointerów.
Przeczytaj to: http://en.wikipedia.org/wiki/Rule_of_three_%28C%2B%2B_programming%29 ad samego zarządzania zasobami. Przy okazji masz tam linki do tego co to konstruktor kopiujący, operator przypisania, etc., z którymi powinieneś się zapoznać.