Rosnące zużycie pamięci w grze

0

A więc problem rysuje się tak (w uproszczeniu bo pomijam kwestie menu oraz intro gry):

  1. Wchodzę do gry, wskaźnik wskazuje na Poziom1, uruchamia się konstruktor Poziom1, gra ma zużycie, pokazywane przez menadżer zadań, około 15mb.
  2. Przechodzę Poziom1, zmienna nowaGra zostaje zinkrementowana i wskaźnik wskazuje na Poziom2.
  3. Przyjmijmy w uproszczeniu, że każdy poziom ma takie same zużycie pamięci. Chciałby uzyskać efekt taki, że kiedy wchodzę do Poziomu2 to zużycie nadal jest 15, a tu jednak wynosi ono 30.
  4. Wniosek z tego taki wysnułem, że kiedy przechodzę do kolejnych poziomów to te poprzednie gdzieś tam jeszcze zalegają.

Żeby to zobrazować, tak u mnie wyglądają klasy poziomów. Klasa bazowa PoziomBazowy i dziedziczące po niej konkretne poziomy.

class PoziomBazowy
{
protected:        
        //...
        Tekstura Tlo;
        Postac Gracz;
        sf::Clock timer;
        //...
public:
        //...
        virtual void Wyswietl(sf::RenderWindow &Okno, sf::Event &Zdarzenie, int &kliknieto, int &posX, int &posY, int &nowaGra);
       //...
};
//////////////////////////////////////////////////////
class Poziom1: public PoziomBazowy
{
private:        
        //...
        Klucz Klucz;
        Drzwi Drzwi;
        //itd itd..
public:
        void Wyswietl(sf::RenderWindow &Okno, sf::Event &Zdarzenie, int &kliknieto, int &posX, int &posY, int &nowaGra);
        //...
};
////////////////////////////////////////////////////// 

W klasie Gra w taki sposób zmieniam te poziomy.

 
PoziomBazowy *Poziom;
 
// i ustawiam go brzydkimi ifami, ale nie wymyśliłem jeszcze ładniejszego sposobu niż if if-elsy bądź switch.
 
        if(nowaGra == 1) Poziom = new Poziom1(); 
        if(nowaGra == 2) Poziom = new Poziom2(); 
        if(nowaGra == 3) Poziom = new Poziom3();
        if(nowaGra == 4) Poziom = new Poziom4();
        if(nowaGra == 5) Poziom = new Poziom5(); 
        if(nowaGra == 6) Poziom = new Poziom6(); 
 
//i potem wywołanie metody:
 
Poziom->Wyswietl(*Okno, Zdarzenie, kliknieto, posX, posY, nowaGra);

Co jest nie tak w takim podejściu, że dzieje się coś takiego? Czy to może w ogóle wynikać z tego czy problem raczej jest gdzieś głębiej? W innym temacie proponowano mi użycie shared_ptr, ale dopiero co o nim usłyszałem i nie wiem jak stosuje się inteligentne wskaźniki.

1

Juz odpisywalem na ten kod. Albo dbaj o zwalnianie pamieci albo przeczytaj te linki, ktore Ci wyslalem.

2

Możesz użyć smart pointers z boost albo zwalniać ręcznie. Jeśli ręcznie to robisz:

        if(nowaGra == 1)
        {
                delete Poziom;
                Poziom = new Poziom1(); 
        }
// przed kolejnymi if dodaj else - po co mają być sprawdzane kolejne warunki jak jeden jest aktualnie prawdziwy?
// robisz podobnie z delete dla reszty
1
 W innym temacie proponowano mi użycie shared_ptr, ale dopiero co o nim usłyszałem i nie wiem jak stosuje się inteligentne wskaźniki.

Teraz czas na odpowiedz na Twoje pytanie, przepraszam ale nie doczytalem na poczatku ;P

Otoz inteligentny wskaznik w C++, to taki wskaznik, ktory "sam spuszcza po sobie wode". Jest to implementowane za pomoca zwyklego szablonu (wytyczne dotyczace poszczegolnej implementacji sa opisane tutaj: http://en.cppreference.com/w/cpp/memory/shared_ptr, zapraszam do przeczytania jesli Cie to interesuje).

Wskaznika tego uzywa sie dosc dziwnie (przynajmniej dla mnie), ale zapewnia on dosc duzy komfort i oszczedza mile spedzonych chwil z debuggerem :P

Tworzenie:

shared_ptr<A1> pointer(new B1);

Jak widzisz, nie taki diabel straszny:

  1. W nawiasach trojkatnych podajemy typ jakiego maja byc ow wskazniki,
  2. W nawiasach zwyklych podajemy ten obiekt, ktory chcemy zeby byl zarzadzany.

Odwolanie:

pointer->p();

Odwolujemy sie identycznie jak do zwyklego wskaznika, co wiecej mozemy rowniez odwolywac sie tak:

(*pointer).p();

Co zamiast wskaznika zwroci referencje do zarzadzanego obiektu.
Korzystanie jest identyczne jak ze zwyklymi wskaznikami.

Zmiana wartosci:
Tutaj sa drobne schodki bo z tego co wiem nie da sie tego po prostu wykonac i trzeba uzyc funkcji reset():

pointer.reset(new B2);

W sumie to by bylo na tyle, ponizej masz krotki kod testowy, pokazujacy, ze obiekty sa faktycznie usuwane z pamieci i ze to faktycznie dziala:
http://ideone.com/2QFR80

Drugi sposob zostal opisany wyzej przez uzytkownika @Hostel

0

Dzięki bardzo Wam obu za pomoc :) Zabieram się za kodowanie, mam nadzieje, że rozwiąże to mój problem. Jeśli nie to by znaczyło, że coś niepożądanego się dzieje wewnątrz poziomów, ale to już tak łatwo do tego nie dojdę. Dzięki jeszcze raz :)

Tylko musze korzystać z shared_ptr z biblioteki boost, bo z memory mi 2008 express nie rozpoznaje.

EDIT: Problem rozwiązany, dziękuje :)

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