Narzędzia użytkownika

Narzędzia witryny


wlasne_funkcje_obslugi_braku_pamieci

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;

}

wlasne_funkcje_obslugi_braku_pamieci.1228339491.txt.gz · ostatnio zmienione: 2008/12/03 22:24 przez marcinkaczor