double free or corruption
-
Streams brauchst du nicht zu schließen, die machen das schon von alleine wenn sie den Scope verlassen. Wenn du noch andere solche "Verbesserungen" im Programm hast, kommen wir der Sache langsam auf die Spur.
-
Lass das Programm mal mit valgrind laufen und sieh nach, ob es Fehler meldet.
-
Außerdem: Aus einem Destruktor heraus eine Exception zu werfen kann recht böse ausgehen. Der Destruktor wird nämlich auch aufgerufen, wenn das Objekt bei der Behandlung einer anderen Exception aufgerufen wird - und wenn du dann eine zweite Exception hinterherwirfst, weiß das Programm nicht mehr, was es machen soll.
-
Hab ich jetzt einen Stahlbetonträger vor dem Kopf oder kann man bei einem std::vector<T> doch nur T speichern, und keine abgeleiteten Klassen? In Java wär das ja was ganz anderes. Oder Mit einem std::vector<T*>.
-
Java ist kein C++. Nimm einen vector<T*>.
-
Cachus schrieb:
Hab ich jetzt einen Stahlbetonträger vor dem Kopf oder kann man bei einem std::vector<T> doch nur T speichern, und keine abgeleiteten Klassen?
Das hast du richtig erkannt - ein vector<T> speichert T-Objekte. Und wenn du versuchst, etwas anderes reinzupacken, greift das Slicing (d.h. das übergebene Objekt wird in ein blankes T zurechtgestutzt). Für polymorphe Container (die auch abgeleitete Klassen verarbeiten können) benötigst du Zeiger (entweder nackt wie in vector<T*> oder versteckt in einem boost::ptr_vector<T>).
-
Cachus schrieb:
Hab ich jetzt einen Stahlbetonträger vor dem Kopf oder kann man bei einem std::vector<T> doch nur T speichern, und keine abgeleiteten Klassen? In Java wär das ja was ganz anderes. Oder Mit einem std::vector<T*>.
Hast du völlig recht...
Es wird der Copy-Konstruktor der Basisklasse aufgerufen, wodurch das Verhalten wohl anders ist als gewollt...
-
Das hast du richtig erkannt - ein vector<T> speichert T-Objekte. Und wenn du versuchst, etwas anderes reinzupacken, greift das Slicing (d.h. das übergebene Objekt wird in ein blankes T zurechtgestutzt). Für polymorphe Container (die auch abgeleitete Klassen verarbeiten können) benötigst du Zeiger (entweder nackt wie in vector<T*> oder versteckt in einem boost::ptr_vector<T>).
Wie vermeide ich bei einer solchen Lösung Speicherlecks, weil da muss ich ja zwangsläufig die Fehler auf dem Heap initialisieren.
Hmm, daran mag es liegen. Was meine "Verbesserung" angeht, das sollte eigentlich nur eine Schnelllösung darstellen, was anderes von dieser Art habe ich nicht.
-
Indem du boost::ptr_vector verwendest, oder einen vector<unique_ptr> oder einen vector<shared_ptr>
-
Jud4s schrieb:
Das hast du richtig erkannt - ein vector<T> speichert T-Objekte. Und wenn du versuchst, etwas anderes reinzupacken, greift das Slicing (d.h. das übergebene Objekt wird in ein blankes T zurechtgestutzt). Für polymorphe Container (die auch abgeleitete Klassen verarbeiten können) benötigst du Zeiger (entweder nackt wie in vector<T*> oder versteckt in einem boost::ptr_vector<T>).
Wie vermeide ich bei einer solchen Lösung Speicherlecks, weil da muss ich ja zwangsläufig die Fehler auf dem Heap initialisieren.
Der ptr_vector kümmert sich afaik darum, die Elemente per delete freizugeben, wenn er zerstört wird. Bei einem normalen vector muß sich der Besitzer darum kümmern, vor seiner Vernichtung die Elemente zu delete'n.
(Alternativ kannst du Smart-Pointer ala boost::shared_ptr oder std::unique_ptr (C++0x) in den vector packen - die räumen auch hinter sich auf)