Benedikt: C++, SDL, OpenGL: Problem mit SDL_Quit()

Beitrag lesen

Hallo,

ich hoffe das sich in diesem Forum min. 1 jemand befindet der sich mit meinem Problem auskennt. (Das ist ja wieder mal ein Deutsch. Aber ich glaube ihr wisst was ich meine.)

Nun gut.

Ich arbeite zurzeit an einem Projekt das sehr gross werden wird.
Das Problem das ich habe schleppe ich schon seit geraumer Zeit mit dem Projekt mit, aber bis jetzt habe ich das Problem immer verdrängt und desen Lösung auf später verschoben.
Habe auch mit Google immer wieder Suchen bezüglich meines Problems durchgeführt. Aber nicht einmal ansatzweise eine ähnliches Problem gefunden, geschweige den desssen Lösung.
Nun will ich das Problem aber endlich aus der Welt schaffen. Wie gesagt mein Projekt ist schon etwas sehr weit fortgeschritten und das heist das es auch ziemlich viel SourceCode gibt.
Die ausführbare kompilierte Datei ist gut 1 MB gross, So kann ich niemals alles hier posten.

Ein paar Informationen zu meinem System:
kernel-2.6.25-14.fc9.x86_64
gnome-session-2.22.3-1.fc9.x86_64
SDL_image-devel-1.2.6-6.fc9.x86_64
SDL_ttf-debuginfo-2.0.9-4.fc9.x86_64
SDL_gfx-2.0.16-5.fc9.x86_64
SDL-devel-1.2.13-3.fc9.x86_64
SDL-1.2.13-3.fc9.x86_64
SDL_gfx-devel-2.0.16-5.fc9.x86_64
SDL-static-1.2.13-3.fc9.x86_64
SDL_ttf-2.0.9-4.fc9.x86_64
SDL_ttf-devel-2.0.9-4.fc9.x86_64
SDL-debuginfo-1.2.13-3.fc9.x86_64
SDL_image-1.2.6-6.fc9.x86_64
SDL_gfx-debuginfo-2.0.16-5.fc9.x86_64
gcc-4.3.0-8.x86_64
libX11-1.1.4-1.fc9.x86_64

2 GB RAM
Intel Celeron D 3,2 GHz
nVidia GeForce 8500 GT, 512 MB
Aktuellste Treiber für Grafikkarte installiert.

Aber ich kann ja mal grob die wichtigsten Code teile für mein Problem zusammen fassen.

Also zuerst initialisiere ich SDL und dann OpenGL ich verwende auch die SDL_ttf, also lade ein paar Fonts.
Damit rendere ich beliebigen Text auf ein SDL_Surface und tu dann diese mit OpenGL auf den Screen rendern. Funktioniert einwandfrei. Nicht unbedingt das schnellste aber es reicht.

  
// Ein teil der init() Funktion  
{  
  writeLog("init()", LOG_INFO);  
  const SDL_VideoInfo* Info = NULL;  
  if(SDL_Init(SDL_INIT_EVERYTHING) != 0) {  
   writeLog("Couldn't init SDL", LOG_ERROR);  
   return EXIT_FAILURE;  
  }  
  
  Info = SDL_GetVideoInfo();  
  if(Info != NULL) {  
   ScreenWidth = Info->current_w / 2;  
   ScreenHeight = Info->current_h / 2;  
   ScreenHalfWidth = ScreenWidth / 2;  
   ScreenHalfHeight = ScreenHeight / 2;  
   ScreenAspect = (float)((float)ScreenWidth / (float)ScreenHeight);  
  } else {  
   ScreenWidth = 800;  
   ScreenHeight = 600;  
   ScreenHalfWidth = 400;  
   ScreenHalfHeight = 300;  
   ScreenAspect = 8.0f / 6.0f;  
   writeLog("Couldn't get Video Infos from SDL", LOG_WARNING);  
  }  
  
  int videoFlags = SDL_OPENGL | SDL_GL_DOUBLEBUFFER | SDL_HWPALETTE;  
  if(Info->hw_available) {  
   videoFlags |= SDL_HWSURFACE;  
  } else {  
   videoFlags |= SDL_SWSURFACE;  
  }  
  if(Info->blit_hw) {  
   videoFlags |= SDL_HWACCEL;  
  }  
  
  
  SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1);  
  
  Screen = SDL_SetVideoMode(ScreenWidth, ScreenHeight, Info->vfmt->BitsPerPixel, videoFlags);  
  if(Screen == NULL) {  
   writeLog("Couldn't init Video Mode", LOG_ERROR);  
   return EXIT_FAILURE;  
  }  
  
  SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, 0);  
  
  
  if(TTF_Init() == -1) {  
   writeLog("Couldn't init TTF", LOG_ERROR);  
   return EXIT_FAILURE;  
  }  
  
  if(!fileExists("data/verdana.ttf")) {  
   writeLog("\"data/verdana.ttf\" is missing.", LOG_ERROR);  
  }  
  
  if(!fileExists("data/comic.ttf")) {  
   writeLog("\"data/comic.ttf\" is missing.", LOG_ERROR);  
  }  
  font1_16 = TTF_OpenFont("data/verdana.ttf", 16); if(font1_16 == NULL) {   writeLog("Couldn't load TTF-File: \"data/verdana.ttf\"", LOG_WARNING);  return EXIT_FAILURE; }  
  font1_28 = TTF_OpenFont("data/verdana.ttf", 28); if(font1_28 == NULL) {   writeLog("Couldn't load TTF-File: \"data/verdana.ttf\"", LOG_WARNING);  return EXIT_FAILURE; }  
  font1_48 = TTF_OpenFont("data/verdana.ttf", 48); if(font1_48 == NULL) {   writeLog("Couldn't load TTF-File: \"data/verdana.ttf\"", LOG_WARNING);  return EXIT_FAILURE; }  
  font1_56 = TTF_OpenFont("data/verdana.ttf", 56); if(font1_56 == NULL) {   writeLog("Couldn't load TTF-File: \"data/verdana.ttf\"", LOG_WARNING);  return EXIT_FAILURE; }  
  font2_16 = TTF_OpenFont("data/comic.ttf", 16); if(font2_16 == NULL) {   writeLog("Couldn't load TTF-File: \"data/comic.ttf\"", LOG_WARNING);  return EXIT_FAILURE; }  
  font2_28 = TTF_OpenFont("data/comic.ttf", 28); if(font2_28 == NULL) {   writeLog("Couldn't load TTF-File: \"data/comic.ttf\"", LOG_WARNING);  return EXIT_FAILURE; }  
  font2_48 = TTF_OpenFont("data/comic.ttf", 48); if(font2_48 == NULL) {   writeLog("Couldn't load TTF-File: \"data/comic.ttf\"", LOG_WARNING);  return EXIT_FAILURE; }  
  font2_56 = TTF_OpenFont("data/comic.ttf", 56); if(font2_56 == NULL) {   writeLog("Couldn't load TTF-File: \"data/comic.ttf\"", LOG_WARNING);  return EXIT_FAILURE; }  
  
  SDL_ShowCursor(true);  
  SDL_EnableUNICODE(0);  
  
  glViewport(0, 0, ScreenWidth, ScreenHeight);  
  glMatrixMode(GL_PROJECTION);  
  glLoadIdentity();  
  glClearDepth(1.0f);  
  glEnable(GL_DEPTH_TEST);  
  glDepthFunc(GL_LEQUAL);  
  gluPerspective(45.0f, ScreenAspect, 0.1f, 100.0f);  
  glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);  
  glClearColor(0.0f, 0.0f, 0.0f, 0.0f);  
  glShadeModel(GL_SMOOTH);  
  glDisable(GL_CULL_FACE);  
  
  atexit(TTF_Quit);  
  atexit(SDL_Quit);  
 }

Hier wird dann jede menge Zeugs gerendert und berechnet.

Dann am Ende gebe ich die Fonts frei mit TTF_CloseFont() und die ScreenSurface mit SDL_FreeSurface() dann rufe ich TTF_Quit() auf und
 schließlich SDL_Quit() gleich nach SDL_Quit() kommt der aufruf exit(EXIT_SUCCESS). j

~~~c++

{ // Der letzte Teil der exit() Funktion
  writeLog("exit()", LOG_INFO);
  writeLog("Close Fonts", LOG_INFO);
  if(font1_16 != NULL) {  TTF_CloseFont(font1_16); }
  if(font1_28 != NULL) {  TTF_CloseFont(font1_28); }
  if(font1_48 != NULL) {  TTF_CloseFont(font1_48); }
  if(font1_56 != NULL) {  TTF_CloseFont(font1_56); }
  if(font2_16 != NULL) {  TTF_CloseFont(font2_16); }
  if(font2_28 != NULL) {  TTF_CloseFont(font2_28); }
  if(font2_48 != NULL) {  TTF_CloseFont(font2_48); }
  if(font2_56 != NULL) {  TTF_CloseFont(font2_56); }

writeLog("Free Screen Surface", LOG_INFO);
  if(Screen != NULL) {  SDL_FreeSurface(Screen); }

writeLog("Call TTF_Quit()", LOG_INFO);
  TTF_Quit();
  writeLog("Call SDL_Quit()", LOG_INFO); // Letzte Ausgabe in Logfile, danach absturz von Programm und XServer
  SDL_Quit();
  writeLog("Call exit()", LOG_INFO);
  exit(EXIT_SUCCESS);
 }

  
So und da mein Projekt auch sehr umfangreich ist habe ich auch ein Logfile wo das wichtigste mitgeloggt wird.  
  
Wenn ich nun mein Programm starte tut es das was ich mir davon erwarte. Alles einwandfrei. Wenn ich nun die [ESC] taste betätige oder das Fenster mit der Maus schließe wird intern der exit() pfad eingeschlagen.  
 Das heisst das Rendern des nächsten Frames wird nicht ausgeführt stattdessen wird mein Programm zum beenden vorbereitet. Das heisst sämtliche Resourcen werden freigegeben und dann meine Fonts,  
 ScreenSurface und TTF\_Quit() SDL\_Quit() wird aufgerufen.  
  
Wenn ich das mache ist der letzte Eintrag in mein Logfile vor dem SDL\_Quit() danach kommt nix mehr. Noch dazu wird mein XServer gleich mit beendet.  
  
Daraus schließe ich das SDL\_Quit() mein Programm zerschiesst und meinen XServer gleich mit. Aber ich finde nirgends einen Hinweis warum.  
  
Vom XServer erhalte ich nach dem Absturz folgende Meldung:  
  
  
  
Backtrace:  
0: /usr/bin/X(xf86SigHandler+0x65) [0x479ca5]  
1: /lib64/libc.so.6 [0x30410322a0]  
2: /usr/lib64/xorg/modules/extensions//libglx.so(\_\_glXDeassociateContext+0x35) [0x7f7d46bf3265]  
3: /usr/lib64/xorg/modules/extensions//libglx.so(\_\_glXContextDestroy+0xf) [0x7f7d46bef63f]  
4: /usr/lib64/xorg/modules/extensions//libglx.so [0x7f7d46bf24f1]  
5: /usr/lib64/xorg/modules/extensions//libglx.so(\_\_glXFreeContext+0x6c) [0x7f7d46bf17cc]  
6: /usr/lib64/xorg/modules/extensions//libglx.so [0x7f7d46bf1813]  
7: /usr/bin/X(FreeResourceByType+0x105) [0x42ea45]  
8: /usr/lib64/xorg/modules/extensions//libglx.so [0x7f7d46bee12e]  
9: /usr/lib64/xorg/modules/extensions//libglx.so [0x7f7d46bf1ae2]  
10: /usr/bin/X(Dispatch+0x364) [0x4467f4]  
  
11: /usr/bin/X(main+0x45d) [0x42cc4d]  
12: /lib64/libc.so.6(\_\_libc\_start\_main+0xfa) [0x304101e32a]  
13: /usr/bin/X(FontFileCompleteXLFD+0x281) [0x42c029]  
  
Fatal server error:  
Caught signal 11.  Server aborting  
  
  
  
Vielleicht hilft das was.  
Wie gesagt sonst finde ich in keinem Logfile irgendeinen Hinweis.  
In der SDL\_Quit() muss irgendetwas vor sich gehen was diesen Bug verursacht. Kann ich da die SDL falsch verwendet haben, sodass die Aufräumroutine von SDL um sich schiesst?  
Aber ich kann doch nicht einfach den SDL\_Quit() aufruf komplett weglassen.  
  
Ich habe mein Projekt auch noch auf keinem anderen System getestet z. B. Windows oder sowas. Der Hauptgrund dafür ist das ich kein Microsoft-Produkt besitze, auch kein Windows. Ich kann auch auf keinem mir zugänglichen Windows-PC ausführlichere Tests durchführen, das ist ein Ding der unmöglichkeit. Zudem ist mein Programm auf Linux optimiert/spezialisiert geschrieben.  
  
Also das wäre echt toll wenn es hier jemand gibt der mir Helfen kann.  
Vielen Dank erstmal wenn ihr euch zumindest mein Problem bis hierher durchgelesen habt.  
  
  
Grüße  
  
Benedikt