Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

1

07.12.2007, 00:39

Segmentation Fault beim SDL_LoadBMP innerhalb einer Instanz

Hallo!

Ich habe hier ein "kleines" Problem, das mich jetzt schon einige Stunden beschäftigt. Das (C++) Programm um das es geht ist ein Parallax-2D-Shooter, was aber für die eigentliche Problematik belanglos sein sollte.

Meine main.cpp sieht auszugsweise so aus:


C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <stdlib.h>
#include "main.h"
#include <SDL/SDL.h>
int main(int argc, char *argv[]){
   SDL_Surface *screen;
   SDL_Event event;
   Uint8 *keys;
 
   int done = 0;

    if (SDL_Init(SDL_INIT_VIDEO) == -1) {
      printf("Can't init SDL:  %s\n", SDL_GetError());
           exit(1);
   }
   atexit(SDL_Quit);
   screen = SDL_SetVideoMode(640, 480, 16, SDL_HWSURFACE | SDL_DOUBLEBUF);
   if (screen == NULL) {
           printf("Can't set video mode: %s\n", SDL_GetError());
           exit(1);
   }


Nichts besonderes, funktioniert auch soweit.

Ich instanziiere also meine Klasse playership:

C-/C++-Quelltext

1
playership *ship;


und erstelle ein initiales Spielershiff:

C-/C++-Quelltext

1
ship->createplayer("player_unscaled.bmp",100,100);


Meine dazugehörige Klasse sieht etwa so aus:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
class playership {
        public:
                [...]
                int createplayer (char bitmappath[100], int startx, int starty) {
                        ship1 = SDL_LoadBMP(bitmappath);
                        if (ship1 == NULL) {
                                return 1;
                        } else {
                                SDL_SetColorKey(ship1, SDL_SRCCOLORKEY, SDL_MapRGB(ship1->format, 255, 255, 255));
                                [...]


Dieser Code alleine funktioniert, ich erhalte eine Instanz und kann mein Schiff über den Bildschirm fliegen. Versuche ich jetzt aber ein anderes Bitmap zu laden, sei es jetzt in einer anderen Klasseninstanz oder direkt in main, bekomme ich einen Segmentation Fault. Lade ich meine Bitmaps nur über Surfaces die sich unmittelbar in main befinden, funktioniert alles wunderbar.
Als ich angefangen hatte meine Spielelemente in Klassen auszulagern, hat dieser Codeteil in ähnlicher Form auch mit anderen Surfaces zusammen funktioniert. Nach dem Hinzufügen einer weiteren Klasse lief nichts mehr, auch nachdem ich den neuen Code auskommentiert hatte.

Beim Versuch das ganze zu debuggen ist gdb jedesmal am SDL_LoadBMP hängen geblieben. Ich habe mal etwas gegooglet, habe da aber nur Hinweise auf Speicherverletzungen gefunden, die nicht unbedingt mit dieser Load-Zeile zusammen hängen.

Da ich erst seit einigen Tagen C++ programmiere, stehe ich etwas verlassen da. Nach 4 Stunden googlen und fruchtlosem rumprobieren sinkt leider auch die Motivation.

Vor allem, weil das Spiel an sich funktioniert, ich das aber gerne etwas OOP-konformer umsetzen will ;)

Falls das irgendwie hilft: Ich kompiliere das ganze mit GCC 4.1.1 (der auch keine Fehler beim Komplilieren meldet), als IDE steht mir vim 7.1 zur Verfügung ;), als Betriebssystem benutze ich Gentoo.

Auf Wunsch kann ich weitere Teile des Quellcodes posten, habe jetzt erstmal nur Teilstücke rausgesucht, die in meinen Augen relevant sind.

Gruß, pyr0

2

07.12.2007, 09:27

Willkommen in diesem Forum erstmal :)

Hast du das mal ausprobiert:

C-/C++-Quelltext

1
int createplayer (char* bitmappath, int startx, int starty)


Ansonsten würde ich das mal hardcoden, um den Fehler einzugrenzen:

C-/C++-Quelltext

1
2
3
ship1 = SDL_LoadBMP("player_unscaled.bmp");
// Oder

ship1 = SDL_LoadBMP(TEXT("player_unscaled.bmp"));

ggf. Pfad mit angeben "MyPlayers/player_unscaled.bmp"

ship1 ist vom Typ SDL_Surface nehm ich mal an? (Hab mit der SDL nix am Hut)

3

07.12.2007, 10:28

Hallo,

danke erstmal für die Antwort ;)

Wenn ich

C-/C++-Quelltext

1
int createplayer (char* bitmappath, int startx, int starty)


daraus mache, bekomme ich den hier:

Zitat


main.h:24: error: cannot convert 'char**' to 'const char*' for argument '1' to 'SDL_RWops* SDL_RWFromFile(const char*, const char*)'


Hardcodiert habe ich das schon probiert, das war eine der ersten Dinge die ich versucht habe. (inkl. Pfadangabe)

ship 1 ist ein Surface, das ist beim kopieren nicht mit reingerutscht:

C-/C++-Quelltext

1
2
3
private:
                SDL_Surface *ship1;
                SDL_Rect position;


Ein Versuch, ship1 public zu machen und direkt in main zu belegen ist auch fehlgeschlagen :?

4

07.12.2007, 11:18

Und als du es hardcodiert hast, hat es funktioniert?
Scheinbar gibt es da ein Adressierungsproblem.
Laut Doku: SDL_Surface *SDL_LoadBMP (const char *file);
Schonmal diesen hier probiert:

char* filename = "the.bmp";
SDL_Surface* surface = SDL_LoadBMP(filename);

oder

string filename;
SDL_Surface* surface = SDL_LoadBMP(filename.c_str());
???

5

07.12.2007, 13:46

Das werde ich später mal ausprobieren, melde mich dann mit den Ergebnissen ;)

rklaffehn

Treue Seele

Beiträge: 267

Wohnort: Braunschweig

  • Private Nachricht senden

6

07.12.2007, 18:45

Re: Segmentation Fault beim SDL_LoadBMP innerhalb einer Inst

Zitat von »"pyr0skull"«

C-/C++-Quelltext

1
playership *ship;


und erstelle ein initiales Spielershiff:

C-/C++-Quelltext

1
ship->createplayer("player_unscaled.bmp",100,100);



Ich hoffe doch, dass du nicht einfach einen Zeiger erzeugst ohne den Speicher für das Objekt dahinter anzufordern. Das muss über kurz oder lang schiefgehen.

Richtig wäre:

C-/C++-Quelltext

1
2
playership* ship = new playership;
playership->createplayer("player_unscaled.bmp",100,100);


Wenn du keinen Speicher anforderst, crashed das ganze an der ersten Zuweisung auf ein Klassenmember und das ist eben die Zeile

C-/C++-Quelltext

1
ship1 = SDL_LoadBMP(bitmappath);
.

Das Gemeine an der Sache ist, der Compiler kann das nicht wissen -- und deshalb auch nicht warnen, und das muss nicht immer sofort einen SEGV erzeugen, wenn z.B. der unitialisierte Zeiger zufällig auf Speicher zeigt, den du auch beschreiben darfst.

Wenn sowas gutgeht, sind das die am schwersten zu findenden Fehler, die man machen kann, weil die Probleme meist erst an einer ganz anderen Stelle auftreten.

In diesem Sinne,
Rainer

PS: das ist übrigends kein C++ speziellen Problem, in C wäre das genauso falsch gewesen, nur hat mit fehlendem "malloc" statt "new".
God is real... unless declared integer.
http://www.boincstats.com/signature/user_967277_banner.gif

7

07.12.2007, 21:01

Danke, jetzt weiß ich bescheid und kann weitermachen 8) Ich melde mich dann wenn ich das ausprobiert habe, denke aber daran hat's gelegen, macht ja auch Sinn ;)

8

08.12.2007, 00:36

Wunderbar, das hat funktioniert, somit steht der Objektorientierung nichts mehr im Wege 8)

Vielen Dank für den Tipp!

9

08.12.2007, 07:57

War wohl das hier

C-/C++-Quelltext

1
playership* ship = new playership;


oder?!

Dann könnt ich mich in den A.... beissen, daß ich sowas immer als gegeben voraussetze
und vor lauter Code das Modul nicht sehe... :evil: :(


Zitat von »"F_Beckenbauer1"«

Ja gutt, äh..., i sog amoi, da hätt da Mikkie schon besser aufpassen müssen! 8)

rklaffehn

Treue Seele

Beiträge: 267

Wohnort: Braunschweig

  • Private Nachricht senden

10

08.12.2007, 09:54

Wenn ich uninitialisierte Variablen sehe, speziell Zeiger, dann gehen bei mir hier im Forum immer gleich alle Alarmsirenen an. :)
God is real... unless declared integer.
http://www.boincstats.com/signature/user_967277_banner.gif

Werbeanzeige