Autor Wątek: Problem ze wskaźnikami  (Przeczytany 747 razy)

Offline Rares

  • Użytkownik
    • Moja strona

# Grudzień 30, 2009, 22:02:11
Mam dwie klasy do gry - jedna od postaci, druga od wczytywania bitmap. W każdej klasie mam zmienną typu SDL_Surface, która jest wskaźnikiem na wczytaną bitmapę. Definiując te zmienne nie mogę ustawić ich wartości na NULL, ale robię to w konstruktorach. Potem w funkcji głównej gry wczytuję bitmapy do zmiennych tych klas. Jedna z funkcji wczytujących tworzy dwa wskaźniki (typu SDL_Surface) dla wczytanej i zoptymalizowanej bitmapy. Pod koniec funkcji zwracam bitmapie jednej z klas wskaźnik do tej zoptymalizowanej bitmapy. Wszystko działa do czasu wyłączenia gry. Pojawią się dziwne problemy. Gra wyświetla poprawnie bitmapę, zamyka się i aplikacja wywala błąd. Myślę, że jest to błąd złego użycia wskaźników. Wcześniej usuwałem je na koniec funkcji main za pomocą SDL_FreeSurface, teraz robię to w destruktorach klas tą samą funkcją. Drugi błąd pojawia się przy debugowaniu. Napisałem prosty logger, który po wczytaniu jednej z bitmap wypisuje do pliku komunikat. Bitmapa się wyświetla, a w logu pojawia się poprawny komunikat. Istnieje również druga instrukcja warunkowa, która wyświetla komunikat o błędzie i zamyka program zwracając przy tym 1. Podczas debuggowania aplikacja zwraca 1, ale nie wypisuje komunikatu o błędzie znajdującego się tuż przed return 1.

W czym może być błąd?

Offline Mr. Spam

  • Miłośnik przetworów mięsnych

Offline Rarrt Rahh

  • Użytkownik

# Grudzień 30, 2009, 22:05:24
Jak możesz to rzuć kodem bo jakoś trudno cię zrozumieć.

Offline Rares

  • Użytkownik
    • Moja strona

# Grudzień 30, 2009, 22:15:27
Cały kod?

CGFX.cpp

Kod: (cpp) [Zaznacz]
#include "GFX.h"

SDL_Surface *CGFX::LoadImage(std::string Filename)
{
LoadedImage = SDL_LoadBMP(Filename.c_str());
if(LoadedImage != NULL)
{
OptimizedImage = SDL_DisplayFormat(LoadedImage);
SDL_FreeSurface(LoadedImage);
}
return OptimizedImage;
}

CGFX.h

Kod: (cpp) [Zaznacz]
#ifndef GFX_H
#define GFX_H

#include <SDL.h>
#include <string>

class CGFX
{
public:
SDL_Surface *LoadedImage;
SDL_Surface *OptimizedImage;
SDL_Surface *LoadImage(std::string Filename);
CGFX()
{
LoadedImage = NULL;
OptimizedImage = NULL;
}
~CGFX()
{
SDL_FreeSurface(LoadedImage);
SDL_FreeSurface(OptimizedImage);
}
};

#endif

Logger.cpp

Kod: (cpp) [Zaznacz]
#include "Logger.h"

void CLogger::Logger(std::string Message)
{
time_t RawTime;
tm * Time;
time(&RawTime);
Time = gmtime(&RawTime);
//Time
if((Time->tm_hour + 1 % 24) < 10) Log << "0" << ((Time->tm_hour + 1) % 24);
if((Time->tm_hour + 1 % 24) >= 10) Log << ((Time->tm_hour + 1) % 24);
Log << ":";
if(Time->tm_min < 10) Log << "0" << Time->tm_min;
if(Time->tm_min >=10) Log << Time->tm_min;
Log << ":";
if(Time->tm_sec < 10) Log << "0" << Time->tm_sec;
if(Time->tm_sec >= 10) Log << Time->tm_sec;
Log << ": ";
Log << Message << std::endl;
Log.flush();
}

void CLogger::CreateLog(std::string Filename)
{
Log.open(Filename.c_str());
}

Logger.h

Kod: (cpp) [Zaznacz]
#ifndef LOGGER_H
#define LOGGER_H

#include <fstream>
#include <string>
#include <ctime>

class CLogger
{
public:
std::ofstream Log;
void CreateLog(std::string Filename);
void Logger(std::string Message);
};

#endif

Pomijam Fighter.cpp (jest tam jedna mała funkcja wczytująca nazwę).

Fighter.h

Kod: (cpp) [Zaznacz]
#ifndef FIGHTER_H
#define FIGHTER_H

#include <SDL.h>
#include <string>

class CFighter
{
public:
std::string Name;
SDL_Surface * Picture;
int Life;
int Strength;
int Agility;
int Speed;
int Condition;
void SetName(std::string Name);
CFighter()
{
Picture = NULL;
}
~CFighter()
{
SDL_FreeSurface(Picture);
}
};

#endif

main.cpp

Kod: (cpp) [Zaznacz]
#include <SDL.h>
#include <fstream>

#include "Fighter.h"
#include "Logger.h"
#include "GFX.h"

SDL_Surface * Window = NULL;

SDL_Rect FighterField;

SDL_Event Event;

bool Exit = false;

CFighter Fighter;
CLogger Log;
CGFX Img;

int main(int argc, char * args[])
{
FighterField.w = 150;
FighterField.h = 220;
FighterField.x = 0;
FighterField.y = 0;

Log.CreateLog("log.txt");

Log.Logger("Initializing...");
SDL_Init(SDL_INIT_EVERYTHING);

Log.Logger("Creating window...");
Window = SDL_SetVideoMode(640, 480, 32, SDL_SWSURFACE);

Log.Logger("Loading images...");
Fighter.Picture = Img.LoadImage("data/boh2.bmp");

if(Fighter.Picture != NULL)
{
Log.Logger("Images successfully loaded.");
}
else
{
Log.Logger("Unable to load image!");
return 1;
}

while(!Exit)
{
while(SDL_PollEvent(&Event))
{
if(Event.type == SDL_QUIT) Exit = true;
}
SDL_BlitSurface(Fighter.Picture, &FighterField, Window, NULL);
SDL_Flip(Window);
}

Log.Logger("Deleting images...");
SDL_FreeSurface(Window);
Log.Logger("Closing SDL...");
SDL_Quit();
Log.Logger("Closing window...");
return 0;
}

Mam nadzieję, że nie pójdzie do POL.

BTW Skąd mogę nauczyć się korzystać z debuggera?

Offline Rares

  • Użytkownik
    • Moja strona

# Grudzień 30, 2009, 22:58:01
Pomoże mi ktoś?

Offline .:NOXY:.

  • Użytkownik
    • Profil

# Grudzień 30, 2009, 23:36:04
Uzywasz Visuala ? To wlacz projekt przez F5 bedzie sie debugowac :) jak wywali bald to debugger sie zatrzyma dojdziesz do problemu poprzez CallStack

lazycoder

  • Gość
# Grudzień 30, 2009, 23:50:26
Pomoże mi ktoś?

Pomoże.

Skoro
...
bool Exit = false;

CFighter Fighter;
CLogger Log;
CGFX Img;

int main(int argc, char * args[])
{ ...

obiekty Fighter i Img są globalne to destruktory tych obiektów zostaną wywołane po SDL_Quit tzn. zostaną wywołane funkcje SDL_FreeSurface, które umieściłeś w destruktorach po tym jak SDL_Quit już wszystko posprząta. Moja rada: oczyść destruktory w CFighter i CGFX z wywołań SDL_FreeSurface, przenieś je do nowych metod w tych klasach i wtedy będziesz jawnie wywoływał te metody przed SDL_Quit.

Offline Rares

  • Użytkownik
    • Moja strona

# Grudzień 31, 2009, 10:00:42
Zrobiłem tak, ale błąd jest gdzieś indziej. Podczas debugu program dochodzi tylko do else i zwraca 1. Błąd jest w funkcji wczytywania bitmapy, lecz gdy odpalam normalnie błąd się nie pojawia. Próbowałem wczytać bitmapy do zmiennych zdefiniowanych w main.cpp, a nie w klasach, ale błąd nadal występuje (program zwraca 1).

Kod: (cpp) [Zaznacz]
#include <SDL.h>
#include <fstream>

#include "Fighter.h"
#include "Logger.h"
#include "GFX.h"

SDL_Surface * Window = NULL;

SDL_Surface * Fighter = NULL;

SDL_Rect FighterField;

SDL_Event Event;

bool Exit = false;

CLogger Log;

int main(int argc, char * args[])
{
FighterField.w = 150;
FighterField.h = 220;
FighterField.x = 0;
FighterField.y = 0;

Log.CreateLog("log.txt");

Log.Logger("Initializing...");
SDL_Init(SDL_INIT_EVERYTHING);

Log.Logger("Creating window...");
Window = SDL_SetVideoMode(640, 480, 32, SDL_SWSURFACE);

Log.Logger("Loading images...");
Fighter = SDL_LoadBMP("data/boh2.bmp");

if(Fighter != NULL)
{
Log.Logger("Images successfully loaded.");
}
else
{
Log.Logger("Unable to load image!");
return 1;
}

while(!Exit)
{
while(SDL_PollEvent(&Event))
{
if(Event.type == SDL_QUIT) Exit = true;
}
SDL_BlitSurface(Fighter, &FighterField, Window, NULL);
SDL_Flip(Window);
}

Log.Logger("Deleting images...");
SDL_FreeSurface(Window);
SDL_FreeSurface(Fighter);
Log.Logger("Closing SDL...");
SDL_Quit();
Log.Logger("Closing window...");
return 0;
}

Po normalnym odpaleniu programu:

Cytuj
09:13:28: Initializing...
09:13:28: Creating window...
09:13:29: Loading images...
09:13:29: Images successfully loaded.
09:13:31: Deleting images...
09:13:31: Closing SDL...
09:13:31: Closing window...

Kiedy debuguję log nie jest nawet tworzony.
« Ostatnia zmiana: Grudzień 31, 2009, 10:14:33 wysłana przez Rares »

lazycoder

  • Gość
# Grudzień 31, 2009, 11:07:34
Zrobiłem tak:
~CGFX()
{
//SDL_FreeSurface(LoadedImage);
//SDL_FreeSurface(OptimizedImage);
}
następnie tak:
~CFighter()
{
//SDL_FreeSurface(Picture);
}
i jeszcze to:
Log.Logger("Deleting images...");
SDL_FreeSurface(Fighter.Picture);
SDL_FreeSurface(Window);
Log.Logger("Closing SDL...");
SDL_Quit();
Log.Logger("Closing window...");
return 0;
}
i wszystko śmiga, że aż miodzik.

Cytuj
Zrobiłem tak, ale błąd jest gdzieś indziej. Podczas debugu program dochodzi tylko do else i zwraca 1. Błąd jest w funkcji wczytywania bitmapy, lecz gdy odpalam normalnie błąd się nie pojawia.

Zastanów się, gdzie powinien być data/boh2.bmp gdy debugujesz.  ;)

Offline Rares

  • Użytkownik
    • Moja strona

# Grudzień 31, 2009, 11:58:55
Teraz działa. Dzięki.

Cytat: lazycoder
Zastanów się, gdzie powinien być data/boh2.bmp gdy debugujesz.

O tym nie wiedziałem, ale po skopiowaniu plików bitmap do folderu głównego aplikacji debug działa.

lazycoder

  • Gość
# Grudzień 31, 2009, 12:38:23
Cytuj
O tym nie wiedziałem, ale po skopiowaniu plików bitmap do folderu głównego aplikacji debug działa.

Albo ustawiasz Working Directory we właściwościach projektu.