probs bei delete auf static pointer (Factory, Singleton,..)
-
Habe sowas: (vereinfacht)
//.h class AClass { public: static *AClass Instance(); static DeleteInstance(); void Foo(); protected: AClass() : bar(true) { }; virtual ~AClass(); private: static AClass *mpInstance; bool bar; }; //.cpp AClass *AClass::mpInstance = NULL; AClass *AClass::Instance() { if( !mpInstance ) { mpInstance = new AClass(); } return mpInstance; } void AClass::DeleteInstance() { delete mpInstance; mpInstance = NULL; } AClass::~AClass() { Foo(); //beim verlassen vom destructor crasht es } void AClass::Foo() { bar = false; }ist doch so ok, oder nicht... aber es kracht genau am ende des destructors...
die zuweisung NULL an mpInstance führt er nicht mehr aus...Wenn ich DeleteInstance() nicht aufrufe, sondern es beim beenden des progs automatisch zerstören lasse, kracht es nicht.... merkwürdig, oder?
kann mir wer sagen, woran es liegen könnte?
-
Dein Code gibt nach Beseitigung der beiden (Tipp-)Fehler bei mir keinen Absturz. Ist Dir genau der Code abgestürzt, oder glaubst Du nur, dass es an dem Code liegt?
class AClass { public: static AClass* Instance(); // *AClass static void DeleteInstance(); // void vergessen ...
-
Ridley schrieb:
Wenn ich DeleteInstance() nicht aufrufe
Wo wird DeleteInstance denn aufgerufen?
-
habe die klasse hier nur zur vereinfachung erstellt... habe gar nicht getestet, ob es in der form auch abstuerzt.
danke, dass du fuer mich das testen uebernommen hast.daraus schliesse ich, dass in der "echten" Klasse irgendwelche member sind, die beim zerstoeren probleme machen. entweder die reihenfolge ist falsch, oder es gibt ausserhalb der klasse noch abhaengigkeiten...
kurz vor programmende rufe ich DeleteInstance auf. Fuer das Projekt, in dem ich die Klasse einsetze, wird man das DeleteInstance nicht brauchen, da man immer mit der einmal erstellten Instanz auskommen wird. Von daher gebe ich mich erstmal damit zufrieden, dass es beim automatischen Zerstoeren beim Programm-ende keine Probleme macht.
Allerdings ist es sauberer, wenn man die Instanz noch vor Ende selbst zerstoert...Ich werde mal schauen, ob ich irgendwelche abhaengigkeiten entdecke. Wird nur ertwas schwer, da ich in der Klasse und auch im restlichen Projekt mehrere Klassen aus einer Library benutze und nicht 100%ig weiss, was dort intern ablaeuft bzw. nicht die Library Klassen debuggen kann.
-
Hallo,
Vielleicht hilft dir ja dieser Text
http://www.oop-trainer.de/Themen/Singleton.html
Hier wird unter anderen ein Weg gezeigt, wie man ohne DeleteInstance auskommt.Ciao
-
Ridley schrieb:
Von daher gebe ich mich erstmal damit zufrieden, dass es beim automatischen Zerstoeren beim Programm-ende
Der Standard garantiert sowas allerdings nicht. Dem BS zu vertrauen mag zwar helfen, ist aber keine definitive Lösung. Ich würde auf jeden Fall versuchen, den Fehler zu finden. Vielleicht gibts ja noch ganz andere Schwachstellen in diesem Zusammenhang.
-
danke fuer den interessanten link!
ja, ich werde da nach suchen, einige moeglichkeiten wuesste ich, sind aber nicht viele.
-
groovemaster schrieb:
Der Standard garantiert sowas allerdings nicht. Dem BS zu vertrauen mag zwar helfen, ist aber keine definitive Lösung. Ich würde auf jeden Fall versuchen, den Fehler zu finden. Vielleicht gibts ja noch ganz andere Schwachstellen in diesem Zusammenhang.
Den Fehler sollte Ridley auf jeden Fall suchen. Allerdings habe ich den Standard so verstanden, dass es garantiert ist, das der Destructor aufgerufen wird. Das hat auch nichts mit dem BS zu tun; das gibt allerhöchstens den nicht freigegebenen Speicher und ähnliche Resourcen wieder frei.
C++ Standard 3.6.3.1 schrieb:
Destructors (12.4) for initialized objects of static storage duration (declared at block scope or at namespace
scope) are called as a result of returning from main and as a result of calling exit (18.3). These objects
are destroyed in the reverse order of the completion of their constructor or of the completion of their
dynamic initialization. If an object is initialized statically, the object is destroyed in the same order as if the
object was dynamically initialized. For an object of array or class type, all subobjects of that object are
destroyed before any local object with static storage duration initialized during the construction of the subobjects
is destroyed.
-
niemand schrieb:
Allerdings habe ich den Standard so verstanden, dass es garantiert ist, das der Destructor aufgerufen wird.
Das ist zwar richtig, hat aber nichts mit dem Thema zu tun. Ridley gibt ja die Ressourcen nicht im dtor frei, sondern macht das explizit über die DeleteInstance Funktion. Und aus C++ Sicht lebt ein mit new erzeugtes Objekt solange, bis es mit delete zerstört wird.
Und dass man den Vorteil von einem dtor mit globalen Instanzen verbinden kann, hat Braunstein ja schon angesprochen.
-
Sorry, hast Recht; habe übersehen, dass der Singleton über einen Pointer realisiert ist (mache ich gewöhnlich nicht so).
Damit wird der Destruktor aber eben genau unter keinen Umständen aufgerufen. Es werden lediglich vom BS ggf. die belegten Ressourcen freigegeben. Wenn der Destructor aber irgendeine Logik enthält (z.B. in ein Protokoll schreiben), passiert das garantiert nicht.
-
Hm, war ein verzwicktes Problem, bzw. ist es immer noch. Eine FremdKlasse aus einer Library ( ClanLib, falls wer kennt...) macht beim zerstören immer Probleme, eagl wo. Es sei denn man lässt sie automatisch wegräumen.
Meine Instanz der Klasse wird jetzt fehlerfrei beseitigt. Um den Crash zu vermeiden, bleibt aber das Object aus der ClanLib-Library noch im Speicher und wird bei Programmende zerstört (ohne Probleme).
danke für die erklärungen und tipps!