Aktion vor dem schließen des Programms ausführen
-
Hi,
ich habe in meinen Programm eine Plugin Engine (basierend auf Lua).
Jedes Plugin ist allerdings dynamisch (=> Pointer) in einer Map.Die Map sieht so aus:
typedef std::map <int, lua_State *> PluginList;
Die Plugins werden per lua_open initialisiert.
Allerdings müssen sie auch mit lua_close wieder geschlossen werden (und damit wird dann auch der gebrauchte Speicher wieder befreit.) Hier liegt das Problem. Wenn der Speicher nicht befreit werden müsste, dann könnte ich das ja (rein theoretisch) weglassen, aber das muss er nunmal.So, da die Funktionen aus dem Lua Script sobald es nötig ist aus der Datei geladen werden, kann ich das Plugin nicht einfach so nach dem Programmstart wieder befreien.
Ich muss quasi vor dem Schließen des Programms noch kurz die Map durchlaufen und jedes darin enthaltene Plugin schließen. Bisher sieht das so aus:
void SEMainWindow::OnClose(wxCloseEvent & WXUNUSED(evt)){ for(int i = 0; i < this->PluginEngine.size(); i++){ lua_close(this->PluginEngine[i]); // speicher befreien, etc. } this->Close(false); } BEGIN_EVENT_TABLE(SEMainWindow, wxFrame) EVT_CLOSE(SEMainWindow::OnClose) END_EVENT_TABLE()
Das ganze gibt mir aber einen dicken Fehler beim schließen, der auf das lua_close zurückzuführen ist. Allerdings funktioniert lua_close z.B. bei einem Tastendruck prima, es muss also an der "Ausführungszeit", also beim schließen liegen. Eine einfache wxMessageBox bekomme ich allerdings angezeigt.
Hat jemand eine Idee, was genau ich falsch mache?
lg.
-
Erstens: Wie sieht denn dieser Fehler aus?
Zweitens: Mein Verdacht wäre, daß du Lücken in der map<> hast und deshalb Einträge freigibst, die du gar nicht reserviert hast. Wenn du wirklich alle vorhandenen Element erwischen willst, nimm lieber Iteratoren. Aber noch besser ist es vermutlich, einen Smart-Pointer zu verwenden, der sich selber um die Freigabe kümmert.
PS: Wie heißt denn die map nun tatsächlich
-
Ich habe gemerkt, dass der Fehler erzeugt wird, weil ich die Funktion zu oft aufrufe und damit nicht vorhandene Objekte "zerstören" will.
Allerdings funktioniert das ganze auch mit den Iteratoren nicht:
PluginList::iterator iter; for ( iter = this->PluginList.begin(); iter != this->PluginList.end(); iter++){ wxMessageBox(wxT("hi!")); }
Nach dem klicken des Buttons zum Beenden gibts dann eine Endlosschleife aus wxMessageBoxen.
-
Sicher, daß es eine Endlosschleife ist? Vermutlich ist die map nur größer als du erwartet hast und du bekommst entsprechend viele Message-Boxen.
-
Da ist auf jeden Fall nur ein Element drin, zum einen weil ich nur eines (wie oben beschrieben) eingesetzt habe, zum anderen, weil .size() mir 1 sagt.
Außerdem bleibt der Iterator immer beim 0. Objekt stehen, obwohl er ja eigentlich weiter gesetzt werden sollte..
-
Es würde dir vielleicht nicht unbedingt helfen, aber du kannst in die map ja shared_ptr<> oder irgendwelche RAII-Objekte stecken, die im Destruktor automatisch lua_close(obj) aufrufen.
-
Ach, du bist mein Retter. Ich habe die lua_close Funktion einfach in den Destruktor von SEMainWindow gehauen, der ja beim schließen der Fensters auch aufgerufen wird. Hoffe ich.
Also keine nörfigen RAII Objekte
Vielen, vielen Dank.
-
Es gibt auch atexit. Für Fenster gibt es evtl. auch einen ondestroy handler, das wäre sicherer als der Destruktor.
-
phlox81 schrieb:
Es gibt auch atexit. Für Fenster gibt es evtl. auch einen ondestroy handler, das wäre sicherer als der Destruktor.
Ne, es gibt bei wxWidgets nur das EVT_CLOSE für einen wxFrame.
-
..Und gerade habe ich gemerkt, dass der Destruktor wirklich nicht aufgerufen wird..
Ich schau mal dass ich irgendwie RAII Objekte in die Map setze..