C++ SDL Parachute Deployed...

Abcd12345

Lt. Junior Grade
Registriert
März 2006
Beiträge
483
Hi,

Ich habe "mal wieder" ein Problem mit der SDL. Ich möchte das eine Klasse eine Instanz einer andern Klasse enthällt nur wenn ich versuche die Instanz im Header zu deklaieren bekomme ich in der Konsole eine Fehlermeldung: Fatal Signal: Segmentation Fault < SDL Parachute Deployed>..

Ich wüsste nicht was ich verkehrt mache:


Hier der Header der Klasse, welche ich einbinden möchte:
Code:
#ifndef HUD_HPP
#define HUD_HPP

#include<string>
#include "Player.hpp"
#include "Sprite.hpp"


class CHUD
{
	
private:

	int m_Coins;
	int m_Lives;

    CSprite HudOBjectGrafic;
	
public:
	
void	LoadHudOBject (string Name,int XPosi,int YPosi);
void	UbdateHudObject (CPlayer &Player, int ObjectKind);
void	RenderHudOBject ();


};

#endif


Und das ist der Header, der Klasse welche die Instanz der Klasse CHUD enthalten soll..
Code:
#ifndef Game_HPP
#define Game_HPP
#include <list>
#include "framework.hpp"
#include "Player.hpp"
#include "Enemy.hpp"
#include "Enemy_Rex.hpp"
#include "AreaScanning.hpp"
#include "Backgroundmap.hpp"
#include "Backgroundmap2.hpp"
#include "Enemy_hotDinosaur.hpp"
#include "FireShot.hpp"
#include "AreaMoveObject.hpp"
#include "DamageObjectUP.hpp"
#include "DamageObjectDown.hpp"
#include "HUD.hpp"

class CGame
{
public:

	CGame();

	//Hauptfunktionen des Spiels
	void Run ();
	void Exit ();

	//Unterfunktionen von Run
	void Testlevel();

	void Livesystem();
	

	//Funktionen für Level
	void AreaAbfragen ();
	
	void EnemyUbdate ();
	void EnemyRendern ();
	void EnemyAreaScanning();

	void HudSystem();

	void AreaStagesUbdate();
	void AreaStagesRender();

	void DamageObjectsUbdate ();
	void DamageObjectsRender ();
	void DamageObjectsScanning ();



private:
	
	//Instanzen
	CPlayer m_Player; //Für Spieler
	CBackgroundmap m_Backgroundmap;
	CEnemy_Rex  m_Enemy;
	CEnemy_HotDinosaur m_Enemy2;
	CFireShot m_Fire_Mario;


	
	CDamgeObjectUP m_DamObjUP;
	CDamgeObjectDown m_DamObjDown;

	//CHUD m_HudObject;
	
	CAreaMoveObject m_Stage;


	//Listen
	list<CAreaScanning> m_lArea; //Liste für Area
	list<CAreaMoveObject> m_lStage; //Liste für Platformen
	list<CDamgeObjectUP> m_lDamageObjUP; //UP
    list<CDamgeObjectDown> m_lDamageObjDown; //DOWN
	list<CBackgroundmap> m_lBackgroundmap;
	


	list<CEnemy> m_lEnemy; //Liste für Gegner
	list<CEnemy_HotDinosaur> m_lEnemy2; // Liste für Spezialfall Feuerdino
	


	//Variablen
	bool m_bContact; //Speichert ob Spielerbodenkontakt hat
	bool m_bListe; //Speichert ob Liste schon gefüllt wurde..
	bool m_bAfterFall; //Speichert ob es nach dem Fall ist


	
};

#endif

Ich würde mich über Hilfe freuen ;)
 
Hoi,

1. In dem Code den du gepostet hast, steht erstmal nichts von SDL. Ich weiss nicht ob du in den Klassen Sprite und Player (die ja included werden) SDL-calls/objekte benutzt. Mehr Informationen hierzu wäre hilfreich.

2. Wenn ich dich richtig verstehe, kompiliert dein Programm, beendet sich aber bei Ausführung mit einem Segfault, wenn du eine Membervariable vom Type CHud im Header deklarierst, sie aber sonst nicht weiter verwendest. Daraus würde ich schließen, dass irgendwas im Konstruktor des CHud-Objekts schiefläuft. Da 2 Membervariablen in CHud Primitiven sind, kann der Fehler also nur im Konstruktor von CSprite liegen. Siehe dazu 1.

3. Alle Object-Files und Binaries mal gelöscht (make clean) ?
 
Zu 1 und 2) Ja CSprite benutzt SDL Funktionen.

Hier ist der Konsturktor von CSprite:

Code:
// Konstruktor
//
// Aufgabe: Zeiger auf Screen holen
//
CSprite::CSprite ()
{
  // Zeiger auf Screen holen
  m_pScreen = g_pFramework->GetScreen ();
  m_bXArea = false;
  m_bYArea = false;
  

} // Konstruktor

Hier ist die Framework Funktion die im Konstruktor von CHUD aufgerufen wird um m_pScreen zu übergeben:
Code:
SDL_Surface *GetScreen () {return m_pScreen;}


Und hier wird m_pScreen bei der SDL Initaliesierung defnieiert
Code:
// Init
//
// Aufgabe: Framework initialisieren
//
bool CFramework::Init (int ScreenWidth, int ScreenHeight,
                       int ColorDepth, bool bFullscreen)
{
  // Alle Systeme der SDL initialisieren
  if (SDL_Init (SDL_INIT_VIDEO | SDL_INIT_TIMER) == -1 )
  {
    cout << "SDL konnte nicht initialisiert werden!" << endl;
    cout << "Fehlermeldung: " << SDL_GetError () << endl;

    Quit ();

    return (false);
  }

  // Vollbild oder Fenstermodus einstellen
  if (bFullscreen == true)
  {
    m_pScreen = SDL_SetVideoMode (ScreenWidth, ScreenHeight, ColorDepth,
                                 SDL_HWSURFACE | SDL_DOUBLEBUF | 
                                 SDL_FULLSCREEN);
  }
  else
  {
    m_pScreen = SDL_SetVideoMode (ScreenWidth, ScreenHeight, ColorDepth,
                                 SDL_HWSURFACE | SDL_DOUBLEBUF);
  }


Zu 3) Ich wüsste jetzt nicht genau was du damit meinst..

Ich hoffe das es ausreicht, was ich gepostet habe ansonsten bin ich gerne bereit noch mehr Codeteile oder Informationen preiszugeben, wenn es zur Lösung des Problems hilft ;)
 
Hmm,
also verdächtig ist auf jeden Fall schon mal
Code:
m_pScreen = g_pFramework->GetScreen ();
Ist g_pFramework eine globale Variable? Wann und von wem wird sie gesetzt?
Globale Variablen solltest du IMMER durch das Singleton-Entwurfsmuster ersetzen, es sei denn du weisst ganz genau was tu tust.....

Was du unbedingt noch machen musst, ist die Überprüfung des Rückgabewertes von SDL_SetVideoMode() auf NULL/nil/0. Wenn dieser Call fehlschlägt schleppst du die ganze Zeit eine ungültige Speicheradresse mit dir rum, das ist DER Grund für einen Segfault. Die Symptome die du aber in deinem ersten Post beschrieben hast lassen aber darauf schließen, dass es daran mit großer Wahrscheinlichkeit nicht liegt.

An den anderen Sachen kann ich jetzt direkt nichts gefährliches erkennen, dazu fehlt mir aber das Wissen über die genaue Struktur deines Programmes, und die Kommunikation zwischen den einzelnen Komponenten.

<edit>
Zu 3.
Die einzelnen Quelldateien werden zuerst kompiliert (Object-Files) und diese Object-Files werden anschließend in eine Binary/Executable gelinkt. Wenn die Abhängigkeiten zwischen Object-File und Quelldatei nur aufgrund der .cpp und nicht der .hpp besteht, können durchaus seltsame Resultate entstehen. Deshalb diese Object-Files und Binary löschen. MS VS bietet da sowas wie Projektmappe bereinigen an, unter Linux mit Makefile macht man es halt mit make clean...
</edit>
 
Zuletzt bearbeitet:
Bei "m_pScreen" handelt es sich um eine private Variabel, die ein Zeiger für den Bildschirm ist. Sie wird hier defieniert und hier kann man auch sehen das g_pFramework eine Singleton Funktion aufruft die mir eine Instanz der Frameworkklasse erzeugt. Dieser Funktionsaufruf wurde nur mit "#define" verändert damit das ganze etwas vereinfacht ist und nicht so viel Schreibarbeit bedeutet.

Code:
#ifndef FRAMEWORK_HPP
#define FRAMEWORK_HPP

#include <iostream>
#include "Singleton.hpp"
#include "Timer.hpp"

using namespace std;

#define g_pFramework CFramework::Get()

class CFramework : public TSingleton<CFramework>
{
  public:
    bool  Init    (int ScreenWidth, int ScreenHeight,
                   int ColorDepth, bool bFullscreen);
    void  Quit    ();
    void  Update  ();
    void  Clear   ();
    void  Flip    ();
    bool  KeyDown (int Key_ID);
    SDL_Surface *GetScreen () {return m_pScreen;}

  private:
    SDL_Surface *m_pScreen;   // Surface für den Screen
    Uint8       *m_pKeystate; // Array für aktuellen Tastaturstatus

};

#endif
Ich hoffe, dass das jetzt hilfreich war und wie gesagt: Wenn ich noch irgendwelche Infos geben muss, damit man mir helfen kann bin ich gerne bereit, dass zu tun, wenn es dazu beiträgt, dass der Fehler gefunden wird ;)
 
Nett gelöst mit dem Singleton. Ich nehm einfach mal an, dass das Muster auch korrekt funktioniert...
Frage: Wo wird CFramework::Init(...) aufgerufen?
Achte darauf dass Konstruktoren alle Member-Pointer mit 0 oder einer korrekten Adresse initialisieren. Dann nimm einen Debugger und schau dir mal die Speicheradresse von m_pScreen an. Alternativ kannst du dir die Adresse auch auf der Kommandzeile ausgeben lassen.
 
Dein Vorschlag hat geholffen das "Bereinigen" hat wunder gewirkt es läuft nun alles optimal. Vielen Dank für den guten Tipp :)
 
Zurück
Oben