Speicherfehler am Anfang eines Vektors
-
Hallo, habe ein Problem mit einem Vektor, ich weiss jedoch noch nicht genau, wo der fehler liegt. Daher schreibe ich mal das nötigste.
Ich habe mir eine eigene Klasse mTrace geschrieben mit einem vector...class mTrace{ public: ... /// add a point to the trace void addPoint(const mPoint& pt){points_.push_back(pt);}; private: int a_; int b_; std::vector<mPoint> points_;Diese Klasse brauche ich beim einlesen einer xml-Datei mittels tinyXML
... mTrace nodeToTrace(TiXmlElement* e) { if (strcmp(e->Value(), "Trace") != 0) throw runtime_error(string("wrong trace ") + e->Value()); mTrace result; ... if (result.points().empty()) {// TODO Speicherkorrektur result.addPoint(mPoint(0, 0)); } for (TiXmlElement* element = e->FirstChildElement(); element; element = element->NextSiblingElement()) { result.addPoint(nodeToPoint(element)); } return result; } ...Beim einlesen habe ich nun das Problem, dass das erste element des Vectors sich zur Laufzeit variiert, d.h. bei jedem Durchlauf der funtkion verändern sich die Werte des ersten Elementes im Vector. Alle anderen stimmen. Da ich bisher keine Lösung des Problems gefunden habe, habe ich es ignoriert, indem ich einfach ein leeres Element hinzugefügt habe (siehe TODO) und bei den Schleifen erst ab dem nächsten Element angefangen habe zu zählen. Keine schöne Art, hat aber funktioniert. Nun muss aber eine Lösung her, da ich die Vektoren teilweise umdrehen muss und somit mein Behilf nicht mehr funktioniert.
Wenn ich nun versuche, das erste Element zu löschen, bekomme ich folgenden Fehlerresult.trace(1).points().erase( result.trace(1).points().begin() );vector::_M_range_check
Für Ideen und Vorschläge bin ich gerne zu haben.
-
Kann du mal den erase-Aufruf zeigen, kann aus der Fehlermeldung eigentlich herauslesen, daß du außerhalb eines Vectors auf Elemente zugreifen willst.
Gruß Kimmi
-
Der erase-Befehl steht im Posting. Schreibe ihn aber gerne nochmal.
Kann eigentlich kein zugriffsfehler sein, da ich den Zeiger auf begin() setze.result.trace(1).points().erase( result.trace(1).points().begin() );vector::_M_range_check
und eine kleine Ergänzung der Funktion points()...
class mTrace{ public: ... /// returns the Points from the Trace std::vector<mPoint> points() const {return points_;}; /// add a point to the trace void addPoint(const mPoint& pt){points_.push_back(pt);}; private: int a_; int b_; std::vector<mPoint> points_;
-
Flaut schrieb:
Kann eigentlich kein zugriffsfehler sein, da ich den Zeiger auf begin() setze.
Sicher, dass der vector nicht leer ist?
-
Was gibt trace(1) zurück? Ist das ein Zugriff auf eine darüberliegende Datenstruktur oder sowas?
Gruß Kimmi
-
points() gibt eine Kopie des Vektors zurück. Das erase wird auf einer anderen Kopie des Vektors aufgerufen als das begin.
Gruss Chris
-
Stimmt, jetzt wo du es sagst :-). Fix wäre die Referenz auf points_ zurückzugeben. Allerdings darf die get-Methode dann nicht mehr const sein und sowas ist nicht gerade feier Stil.
Gruß Kimmi
-
Dann gib der Klasse mTrace doch einfach ne Methode zum Point-Löschen

-
habe die löschen methode geschrieben, aber ich habe noch immer den gleichen Speicherfehler. Vermutlich, da es sich wieder um eine Kopie handelt?
... vector<mPoint>::iterator it = result.trace(1).points().begin(); result.trace(1).remPoint( it ); ...class mTrace{ public: ... /// returns the Points from the Trace std::vector<mPoint> points() const {return points_;}; /// remove a point from the trace void remPoint(const std::vector<mPoint>::iterator &pos){points_.erase(pos);}; /// add a point to the trace void addPoint(const mPoint& pt){points_.push_back(pt);}; private: int a_; int b_; std::vector<mPoint> points_;Aber das ist ja immer noch eine Korrektur, die ja das eigentliche Problem nicht löst. Denn das erste Element des Vektors variiert und dort sitzt der Unruhestifter.
-
Flaut schrieb:
habe die löschen methode geschrieben, aber ich habe noch immer den gleichen Speicherfehler. Vermutlich, da es sich wieder um eine Kopie handelt?
Ja, weil points() immernoch eine Kopie zurückliefert. Lasse points() eine konstante Referenz zurückliefern (oder eine nicht-konstante Referenz, aber dann brauchst Du remPoint() nicht mehr).
Aber das ist ja immer noch eine Korrektur, die ja das eigentliche Problem nicht löst. Denn das erste Element des Vektors variiert und dort sitzt der Unruhestifter.
Möchlich, dass das aus einer ähnlichen Situation herrührt - benutzt Du vielleicht irgendwo den Iterator einer Kopie als Einfügeposition für einen Vector?
-
Die Methode "remPoint" könnte auch einen Index entgegennehmen..
-
Wie kann ich denn die Referenz zurück geben? Ich kann doch in meiner Klasse keine Funktion schreiben, in der ich ein eigenes Element als Referenz bekomme? sonst bin ich wieder bei einer Kopie. Steh ich jetzt auf der Leitung? Ich muss doch auf meinen Vektor in der Klasse zugreifen können, ohne eine Kopie des Vektors, das ist ja auch sehr Speicherhungrig.
und beim Ursprungsproblem nutze ich keinen Iterator. Ich lese mittels nodeToTrace ein, erzeuge mir dort eine Instanz vom Typ mTrace, setze die Werte und gebe die Instanz als Rückgabewert zurück.
mTrace nodeToTrace(TiXmlElement* e) { if (strcmp(e->Value(), "Trace") != 0) throw runtime_error(string("wrong trace ") + e->Value()); mTrace result; const char *traceID, *color, *numPoints; //read Parameter traceID = e->Attribute("traceID"); if (traceID != NULL) result.setTraceID(atoi(traceID)); else throw runtime_error(string("wrong traceID ") + e->Value()); color = e->Attribute("color"); if (color != NULL) result.setColor(atoi(color)); else throw runtime_error(string("wrong color ") + e->Value()); numPoints = e->Attribute("numPoints"); if (numPoints != NULL) result.setNumPoints(atoi(numPoints)); else throw runtime_error(string("wrong numPoints ") + e->Value()); if (result.points().empty()) {// TODO Speicherkorrektur result.addPoint(mPoint(0, 0)); } for (TiXmlElement* element = e->FirstChildElement(); element; element = element->NextSiblingElement()) { result.addPoint(nodeToPoint(element)); } return result; }Dies mache ich geschachtelt, aber immer auf die gleiche Weise readXML(mStructure(mTrace(mPoint()))).