[GELÖST] SDL_TTF und Speicherprobleme bei TTF_CloseFont()
-
Guten Morgen,
ich schlage mich nun schon einige Zeit mit diesen Problem herum, es ist zwar kein schwerwiegendes, aber das Vorhandensein allein wurmt mich.
Zur einfacheren Handhabung von SDL_TTF habe ich mir die Klasse Text geschrieben.
class Text { // VARIABLES std::string fontfile_; int fontsize_; TTF_Font *font_; SDL_Color color_; public: // CONSTRUCTORS Text(); Text(std::string filename, int fontsize = 12); //~Text(); // SETTERS void redefine(std::string filename, int fontsize = 12); // FUNCTIONS int render(std::string text, int x, int y, SDL_Surface *sf, int red = 0, int green = 0, int blue = 0); int renderGL(std::string text, int x, int y, int red = 0, int green = 0, int blue = 0, int alpha = 255, std::string style = ""); };
Der Konstruktor sieht folgendermaßen aus:
Text::Text(std::string filename, int fontsize) : fontfile_(filename), fontsize_(fontsize) { font_=TTF_OpenFont(fontfile_.c_str(), fontsize_); if(!font_) { printf("TTF_OpenFont: %s\n", TTF_GetError()); // handle error } }
Wie zu sehen ist, ist der Destruktor auskommentiert, denn hier liegt das Problem. Ich muss das Objekt font_ zerstören, um die Font-Datei aus dem Speicher zu schmeißen.
Folgender Destruktor sorgt allerdings für einen Speicherzugriffsfehler:
Text::~Text() { TTF_CloseFont(font_); font_=NULL; // to be safe... }
Dieser Code stammt aus der Dokumentation zu SDL_TTF.
Ich bitte um Hilfe bei diesem Problem.
-
Hast du das
Text
-Objekt vorher kopiert, sodass der Destruktor mehrmals aufgerufen wird?
-
TyRoXx schrieb:
Hast du das
Text
-Objekt vorher kopiert, sodass der Destruktor mehrmals aufgerufen wird?Jetzt, wo du es schreibst, ich übergebe das Objekt an einer Stelle an Vektor, erzeuge also ein temporäres Objekt, das ich dann per
push_back()
an den Vektor schiebe.Die einzige mir bekannte Alternative dazu wären die Extended Initializer Lists aus C++0x, aber gäbe es nicht vielleicht eine Lösung, die mit dem jetzigen Standard kooperiert?
-
Auf jeden Fall musst du die Klasse unkopierbar machen. Am besten mit etwas wie
boost::noncopyable
. Zum Speichern der Objekte bieten sich dann verschiedene Möglichkeiten an:
- mitshared_ptr
imvector
- direkt imboost::ptr_vector
- mit Move-Operationen undunique_ptr
imvector
-
TyRoXx schrieb:
Auf jeden Fall musst du die Klasse unkopierbar machen.
Oder kopierbar machen.
-
Nexus schrieb:
TyRoXx schrieb:
Auf jeden Fall musst du die Klasse unkopierbar machen.
Oder kopierbar machen.
Könntest du den Ansatz bitte erklären? Meinst du einen Copy-Konstruktor?
TyRoXx schrieb:
Auf jeden Fall musst du die Klasse unkopierbar machen. Am besten mit etwas wie
boost::noncopyable
. Zum Speichern der Objekte bieten sich dann verschiedene Möglichkeiten an:
- mitshared_ptr
imvector
- direkt imboost::ptr_vector
- mit Move-Operationen undunique_ptr
imvector
Auf Boost würde ich aus diversen Gründen lieber verzichten. Gäbe es nicht eine "native" Möglichkeit?
EDIT:
Ich habe noch etwas herumprobiert und folgenden Code getestet:
int main( int argc, char* argv[] ) { initialize_SDL(); std::map<std::string,Text> mtext; std::vector<Text> vtext; Text text; std::cout << "Füge in Vektor ein" << std::endl; vtext.push_back(text); std::cout << "Erfolg!" << std::endl; std::cout << "Füge in Map ein" << std::endl; mtext.insert( std::pair<std::string,Text>( "bla",text ) ); std::cout << "Erfolg!" << std::endl; return 0; }
Die Map habe ich euch bisher unterschlagen, da ich etwas konfus war und in meinem Code durcheinander gekommen bin, Entschuldigung dafür.
Die Ausgabe ist jedenfalls eindeutig:
Füge in Vektor ein
Erfolg!
Füge in Map ein
SpeicherzugriffsfehlerBei auskommentiertem
TTF_CloseFont(font_);
funktioniert auch das Einfügen in die Map, aber die Font bleibt, wie im Eingangspost geschildert, im Speicher hängen.EDIT2:
Der Speicherzugriffsfehler tritt nur bei einem Objekt vom Typ std::mapstd::string,Text auf. Nehme ich statt des Strings einen Integer oder Ähnliches, funktioniert auch der Kontruktor.
Natürlich könnte ich an dieser Stelle auch mit Integer-Konstanten arbeiten, aber ich bin verwirrt.
Wie kann das sein?
-
Könntest du den Ansatz bitte erklären? Meinst du einen Copy-Konstruktor?
Ja, meint er.
Naiv kannst du für jede Klasse den TTF_Font neu im copy-ctor laden. (auch auf einen korrekten Zuweisungsoperator achten).
Alternativ ref-counting, is wohl die bessere Lösung. Davon die Textklasse non-copyable zu machen halt ich nix, das verleitet dazu irgendwelche umständlichen designs zu nehmen, nur ums nicht kopieren zu müssen.Zum Edit2: Nicht mit integern arbeiten - das Problem ist, das deine Textklasse so nicht richtig kopierbar ist. Nur weils bei int grade geht (undefined behaviour kann ja durchaus auch "mal" funktionieren) solltest du das nicht machen. Bei mtext.insert wird soweit ich sehe wieder prinzipiell wieder der copy-ctor verwendet.
-
Danke, es funktioniert.