To jest stara wersja strony!
/*! * Autor: Marcin Kaczor U3ISI nr albumu: 192641 * Temat: Obsluga braku pamieci (praca domowa na ZPR) * * Problem: Podczas korzystania z dynamicznego przydzialu pamieci w jezyku C++ * (za pomoca operatora new) jesli nie uda sie zarezerwowac bloku pamieci * o odpowiednim rozmiarze, to zostanie rzucony wyjatek std::bad_alloc. * Sprawdzanie czy po każdym wywolaniu new nie zostal rzucony wyjatek jest * klopotliwe. Oczywiscie mozna uzywac wersji operatora new, ktora nie rzuca * wyjatkiem new (std::nothrow) Typ, ale wtedy pomijamy obsługę błędów. * * Opis: Bilbioteka standardowa udostepnia mozliwosc zdefiniowania wlasnej funkcji * obslugi braku pamieci za pomoca funkcji z biblioteki standardowej set_new_handler(). * Funkcja obslugi braku pamieci powinna uzyskac wiecej pamieci, rzucic wyjatek, * przerwac program lub chociaz ustawic inna funkcje obslugi (lub odinstalowac * obecna), bo program bedzie sie wykonywal w nieskonczonej petli. * * Zastosowanie: Glownym zadaniem funkcji obslugi braku pamieci jest uzyskanie * wiekszej ilosci pamieci (np. przez usuniecie nieuzywanych obiektow) tak aby * aplikacja mogla dzialac dalej, czasami jest to niemozliwe, funkcja ta jest tez * przydatna gdy nie chcemy przy kazdym tworzeniu nowego obiektu obslugiwac * wyjatku bad_alloc, w ten sposob, gdy juz wystapi problem braku pamieci mozemy * to obsluzyc w jednym miejscu i zamknac aplikacje w mniej brutalny sposob, mamy * szanse na pozamykanie polaczen, plikow oraz poinformowanie uzytkownika o tym co * sie stalo. * * Przyklad: Nizej zostanie przedstawiony przyklad klasy reprezentujacej obiekty * zajmujace duzo pamieci, obiekty beda rejestrowane w rejstrze przez ktory tez * jest mozliwy do nich dostep, rejestr bedzie usuwac obiekty gdy bedzie * potrzebna pamiec. */
#include <new> zawiera funkcje set_new_handler #include <iostream> obiekty cout, cerr, etc. #include <cstdlib> exit() - awayjne wyjscie #include <vector> wektor obietktow BigSize
! wielkosc bufora powiekszajacego rozmiar BigSize #define BS_SIZE 200000000 deklaracja klasy Register potrzebna klasie BigSize class Register;
! Klasa BigSize /*! Klasa BigSize reprezentuje duze obiekty w pamieci, np. warstwy w zaawansowanym programie do obrobki grafiki rastrowej lub zapamietywanie histori zmian w obrazie. */ class BigSize { friend class Register; private: ! Prywatny konstruktor, tylko obiekty klasy Register maja prawo tworzyc obiekty
//! BigSize. Dla celow testowych informuje uzytkownika o stworzeniu obiektu BigSize() { std::cout << "Creating BigSize..." << std::endl; }
//! Prywatny konstruktor kopiujacy, zabezpiecza przed kopiowaniem obiektow, //! dostep do obiektu jest mozliwy tylko przez klase register BigSize(const BigSize &) {};
//! Prywatny destruktor, tylko obiekty klasy Register maja prawo niszczyc obiekty //! BigSize. Dla celow testowych informuje uzytkownika o usunieciu obiektu ~BigSize() { std::cout << "Deleting BigSize..." << std::endl; }
private:
//! Tablica znakow, bufor, w przykladzie tylko sztucznie powieksza rozmiar klasy char buffer_[BS_SIZE];
};
! Klasa Register /*! Klasa Register tworzy, usuwa i przechowyje wskazania na obiekty BigSize, zaimplemneotwna jako Singleton, mozna przy implemntacji wykorzystac rowniez wzorzec fabryki */ class Register { private: ! Prywatny konstrukotr domyslny i kopiujacy
Register() : counter_(0) {}; Register(const Register &r);
public:
//! Metoda pobierajaca referencje do obiektu static Register& getInstance() { static Register instance; return instance; }
//! Tworzenie nowego obiektu klasy BigSize BigSize *getNewBigSize() { BigSize *bs = new BigSize(); objects_.push_back(bs); counter_++; return bs; }
//! zwolnienie nieuzywanych obiektow, w tym przykladzie wszystkie obiekty sa nieuzywane //! metoda zwaraca true zostala zwolniona jakakolwiek ilosc pamieci, w przeciwnym razie false bool deleteUnusedObjects() { bool retval = counter_ > 0 ? true : false;
while (counter_--) { delete objects_.back(); objects_.pop_back(); } counter_ = 0; return retval; }
//! Pobranie obiektu klasy BigSize o zadanym indeksie, niewykorzystywane w przykladzie BigSize *getBigSize(int index) { if (index > 0 && index < counter_) return objects_[index]; else return NULL; }
private:
int counter_; /**< licznik obiektow */ std::vector<BigSize *> objects_; /**< wektor obiektow */
};
! Funkcja obslugi braku pamieci, zamyka awaryjnie aplikacje void KillApplication() { informacja dla uzytkownika, w zaleznosci od potrzeb moze byc zapisana do logu
std::cerr << "Pamiec zostala wyczerpana, awaryjne zamykanie aplikacji." << std::endl; // awaryjne zamykanie aplikacji, zapisanie stanu, zamkniecie plikow, polaczen, etc. exit(1);
}
! Funkcja obslugi braku pamieci, sprzata pamiec void CleanUpMemory() { informacja dla uzytkownika, potrzebna raczej tylko dla aplikacji testowej
std::cout << "Pamiec zostala wyczerpana, usuwanie niepotrzebnych obiektow." << std::endl; if (!Register::getInstance().deleteUnusedObjects()) { // nie udalo sie zwolnic pamieci std::set_new_handler(KillApplication); // ustawienie nowej funkcji obslugi braku pamieci return; } exit(1); // program moze kontynuowac dzialanie, bo zwolniono czesc nieuzywanej pamieci, // ale w tym przykladzie dzialalby w petli nieskonczonej, dlatego zostanie zamkniety
}
int main () {
std::set_new_handler(CleanUpMemory); // ustawienie nowej funkcji obslugi braku pamieci for(;;) { Register::getInstance().getNewBigSize(); // zajmowanie pamieci :-) } return 0;
}