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

Beitrag lesen

»»

Also zunächst einmal möchte ich ein paar Dinge korregieren. Das kann ich nicht so hinnehmen.

Du möchtest offenbar gerne, dass Dein Code Anklang findet.

Diese Aussage ignoriere ich mal.

Sorry, aber dazu ist der Code aber einfach nicht gut genug:

Das ist akzeptiert, darauf möchte ich aber später zurückkommen.

Fest "eingebrannte" globale Pfade in den Tiefen irgendeiner Funktion sind eben kein guter Stil; genauso wenig wie "ausgerollte" Schleifen.

Auch dazu später mehr.

Wenn Du solchen Code vorlegst kannst Du nicht erwarten, dass andere Programmierer mit Dir auf Augenhöhe technisch diskutieren.

OK. Das kann ich halbwegs verstehen auch wenn ich da auf den Sinn eines Forums oder eben gerade dieses Forums verweisen könnte.

Ich bin momentan 16 Jahre alt. Lerne Elektroniker für Geräte und System, wollte aber ursprünglich Fachinformatiker für
Anwendungsentwicklung lernen. Aber ein anders Angebot war eben besser und ich bereue es auch keineswegs.
Später möchte ich dann Informatik und Elektrotechnik studieren. Ja, beide.

Im Jahre 2003 habe ich mir ein Buch über C++ und die Spieleprogrammierung von einem bekannten Verlag gekauft.
Damit fing ich an mich für C/C++ und Programmierung allgemein zu interessieren und es schließlich auch zu lernen.
Skriptsprachen usw. kamen erst später ((X)HTML, CSS, JavaScript, Java, PHP und MySQL, auch ein wenig Assembler)
Ich möchte keineswegs behaupten das ich da irgendwo ein Experte bin. Aber ich behaupte das ich von allen ein
wenig Ahnung habe.
Und Lernen ist nicht irgendwann Abgeschlossen, Lernen ist ein fortwährender, endloser Prozess.

Ich habe auch noch nie  mit einem professionellem Programmierer zusammengearbeitet oder geschweige den persönlich gesprochen.
OK, da gibt es jetzt 1 Ausnahme nämlich ein 4 tägiges Praktikum bei einer kleinen Firma. Aber da habe ich nicht so viel
gelernt das es jetzt der Rede wert wäre. Ich habe nur Bücher und das Internet womit ich mein Wissen ausbaue(-n kann).

Deine Probleme sind folgende:

  • Du scheust Dich offenbar davor mit dem Debugger systematisch zu arbeiten:

Und wenn ich was finde, das ist alles SDL intern, da müsste ich ja in der SDL den Fehler ausmerzen. Aber das will ich nicht.

Damit meinte ich eher das ich mit der Entwicklung von SDL nichts zu tun habe, die SDL intern sehr komplex ist, mein stupide Annahme SDL = bugfrei.

Damit stehst Du nicht allein; viele Programmierer, die von Skript-Sprachen zu C/C++ gekommen sind, zeigen dies Verhalten; meist sind fehlende Grundkenntnisse in Assembler das Hauptproblem.

Aber C und C++ sind keine Skript-Sprachen.

Das habe ich schon richtig gestellt, ich habe vor C++ keine andere Sprache gelernt. Grundkenntnisse in Assembler sind sehr wohl vorhanden.

Es nützt aber nichts jahrelang die Sinnlosigkeit von Debug-Sitzungen zu betonen statt sich einmal zu erarbeiten was EAX, ESP... denn wohl bedeuten.

  • Du verwirfst Lösungsansätze ohne sie auszuprobieren:

Dass Du selbst keine eigenen Threads erzeugst ist kein hinreichendes Kriterium; wie hast Du z.B. ermittelt, dass die Bibliotheken keine eigenen Threads erzeugen; etwa für die Oberfläche?

Das kann ich mir sehr schwer vorstellen.

Es ist unerheblich ob wir uns etwas vorstellen können. Test und Analyse  schaffen Gewissheit.

Ich kann sehr wohl lesen. GDB sagt es wird nur ein Thread erstellt und ich glaube das.
Außerdem kenne ich sehr wohl meinen Code. Und da wird nun mal kein 2. Thread erstellt.

Auf diese Hypothese

atexit(irgendwas);

/*und

später */

irgendwas();

riecht nach nach einem free() auf einen nicht genullten Zeiger auf dem »» »» schon mal free() aufgerufen wurde.

bist Du bislang auch nicht eingegangen.

Warum eigentlich nicht?
Was spricht gegen ein "//" vor dem atexit() und ein paar Testläufe?

Den Fehler vermutete ich in Zusammenhang mit meiner Funktion die den Text rendert.
Außerdem habe ich das sehr wohl auch getestet, auch mit debugger.
Die exit() Funktionen liefen immer fehlerfrei, egal wie oft sie aufgerufen wurden. Aber erst nachdem ich den Code ein wenig bearbeitet habe. (Dazu unten mehr)

Wie man obigen Text entnehmen kann habe ich nie irgendwelchen Informatikunterricht besucht.
Mir hat auch nie jemand gesagt wie ich schönen Code zu schreiben habe. Wie ich dies und jenes
Problem Codetechnisch zu lösen habe. Einige Dinge habe ich mit der Zeit verschiedenen Quellen
entnehmen können, aber ich war/bin darauf angwiesen solche Quellen erst einmal zu finden.
Aber ich bin auch ein Verfechter des Selbststudiums, man kann mit der richtigen Motivation
Sachen viel schneller und besser verstehen und lernen auch vorausgesetzt es gibt genug
Quellen mit Information. Aber die Motivation ist sehr ausschlaggebend.

Wenn ich z. B. den Code von irgendeinem OpenSource Projekt anschaue. z. b. gcc,kernel,httpd,o. ä.
So hat der Code viele Unterschiede im Vergleich zu meinem Code. Aber die OpenSource-projekte
wurden von Experten gecodet.
Solchen Code zu schreiben habe ich mir noch nicht beigebracht, ich habe bis jetzt auch nie
die Notwendigkeit gesehen meinen Code/Programmierstil irgendwie drastisch zu verändern.
Bis jetzt konnte ich jedes Problem lösen. Ob die Lösung nun einem Experten gefallen würde
oder nicht, darüber habe ich mir nie Gedanken gemacht. Für mich war wichtig, das Problem ist
gelöst und der Code funktioniert.
Aber wenn ich später ein Informatikstudium beginnen und abschließen möchte und danach einen
(Informatik-)Job habe. So denke ich mir doch das ich meinen Programmierstil/Code vll. doch ein wenig
ändern/verbessern sollte. Da mein Team ja dann auch aus Experten besteht.

Gibt es denn irgendein Buch oder eine Internetseite(Tutorial, Vorlesung, Diplomarbeit, eBook)
über das verfassen von schönem Code, Tabus, goldenen Regeln, Vorschriften, Verboten, Standards
z.B. das mit den

Fest "eingebrannte" globale Pfade in den Tiefen irgendeiner Funktion sind eben kein guter Stil; genauso wenig wie "ausgerollte" Schleifen.

Wie man solche Sachen schön und elegant löst.
Damit ich in Zukunft Code schreiben kann den auch Experten akzeptieren.

Abschließend möchte ich auf mein eigentliches Problem und Thema dieses Threads zurückkommen.

Wie gesagt verdächtigte ich schon länger diese Funktion:

  
 void renderText(const char* text, SDL_Color color, TTF_Font* font, SDL_Rect* location)  
 {  
  if(font == NULL || text == NULL || location == NULL) {  
   writeLog("renderText(): Get a NULL Pointer.", LOG_ERROR);  
   return;  
  }  
  
  SDL_Surface* intermediary = NULL;  
  SDL_Surface* initial = TTF_RenderUTF8_Blended(font, text, color); // Use SDL_TTF to render our text  
  if(initial == NULL) {  
   writeLog("renderText(): TTF_RenderUTF8_Blended() Get a NULL Pointer.", LOG_ERROR);  
   return;  
  }  
  int texture = 0;  
  int w = nextPowerOfTwo(initial->w); // Convert the rendered text to a known format  
  int h = nextPowerOfTwo(initial->h);  
  
  intermediary = SDL_CreateRGBSurface(0, w, h, 32, 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000);  
  
  if(intermediary == NULL) {  
   writeLog("renderText(): SDL_CreateRGBSurface() Get a NULL Pointer.", LOG_ERROR);  
   return;  
  }  
  
  SDL_BlitSurface(initial, 0, intermediary, 0); // copy surface  
  
  glEnable2D();  
  glDisable(GL_DEPTH_TEST);  
  
  glGenTextures(1, (GLuint*)&texture);// Tell GL about our new texture  
  glBindTexture(GL_TEXTURE_2D, texture);  
  glTexImage2D(GL_TEXTURE_2D, 0, 4, w, h, 0, GL_BGRA, GL_UNSIGNED_BYTE, intermediary->pixels);  
  
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);// GL_NEAREST looks horrible, if scaled...  
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);  
  
  glEnable(GL_TEXTURE_2D);// prepare to render our texture  
  glBindTexture(GL_TEXTURE_2D, texture);  
  glColor3f(1.0f, 1.0f, 1.0f);  
  
  glBegin(GL_QUADS);  // Draw a quad at location  
  glTexCoord2f(0.0f, 1.0f); // Recall that the origin is in the lower-left corner That is why the TexCoords specify different corners than the Vertex coors seem to.  
  glVertex2f(location->x,     location->y);  
  glTexCoord2f(1.0f, 1.0f);  
  glVertex2f(location->x + w, location->y);  
  glTexCoord2f(1.0f, 0.0f);  
  glVertex2f(location->x + w, location->y + h);  
  glTexCoord2f(0.0f, 0.0f);  
  glVertex2f(location->x,     location->y + h);  
  glEnd();  
  glFinish(); // Bad things happen if we delete the texture before it finishes  
  glEnable(GL_DEPTH_TEST);  
  glDisable2D();  
  
  location->w = initial->w; // return the deltas in the unused w,h part of the rect  
  location->h = initial->h;  
  
  // Clean up  
  SDL_FreeSurface(initial);  
  initial = (SDL_Surface*)NULL;  
  SDL_FreeSurface(intermediary);  
  intermediary = (SDL_Surface*)NULL;  
  glDeleteTextures(1, (GLuint*)&texture);  
  texture = 0;  
 }

Wie gesagt die Funktion habe ich mir ausgeliehen und abgeändert.
Hatte ich die Funktion im Render-Teil drin. So war die Wahrscheinlichkeit, das
mein Programm Amok läuft um 80% erhöht. Hatte ich den Render-Teil komplett
leer, so war die Wahrscheinlichkeit fast 0%.
Ob das Problem nun gelöst ist kann ich nicht sagen. Jegliche Debug-versuche
bringen nur das Ergebnis das ich ohne Debugger auch erreiche: Program exited normally.
Also ich betrachte das Problem bis auf weiteres für gelöst.

Nun möchte ich meine überarbeitet Version noch kurz posten um zu erfahren ob der Code nun beser ist oder ob es immer noch der gleiche Mist ist.

  
#define FONT_MAX_SIZE (100)  
// 4 Globale Arrays:  
TTF_Font* FontVerdana[(FONT_MAX_SIZE + 1)] = {(TTF_Font*)NULL};  
TTF_Font* FontTahoma [(FONT_MAX_SIZE + 1)] = {(TTF_Font*)NULL};  
TTF_Font* FontCourier[(FONT_MAX_SIZE + 1)] = {(TTF_Font*)NULL};  
TTF_Font* FontComic  [(FONT_MAX_SIZE + 1)] = {(TTF_Font*)NULL};  
  
// In der init() Funktion  
// Wäre da eine Funktion besser, die dann ein mal für jede Schrift aufgerufen wird?  
// Aber dann könnte man ja die 4 Funktionsaufrufe wieder in eine Schleife packen??  
// Aber die festen,globalen Pfade gibt es immer noch?  
// 4 mal das ganze; einmal für jedes Array  
   for(unsigned short i = 0; i < FONT_MAX_SIZE; ++i) {  
   FontVerdana[i] = TTF_OpenFont("data/verdana.ttf", i + 1);  
   if(FontVerdana[i] == (TTF_Font*)NULL) {  
    writeLog("Couldn't open Font \"verdana.ttf\"", LOG_ERROR);  
    return EXIT_FAILURE;  
   }  
  }  
  
  
  
// und exit() Funktion, 4 mal; für jedes Array 1 mal  
  for(unsigned short i = 0; i < FONT_MAX_SIZE; ++i) {  
   if(FontVerdana[i] != (TTF_Font*)NULL) {  
    TTF_CloseFont(FontVerdana[i]);  
    FontVerdana[i] = (TTF_Font*)NULL;  
   }  
  }  
  
  

Das einzige Anliegen das ich noch hätte, wären ein paar Quellen mit Rezepten für schöneren, besseren, schnelleren Code.
Natürlich nur wenn das möglich ist.

Benedikt