Auflösen von out of range-Problemen
-
Servus,
ich erhalte beim Ausführen meines Programms den folgenden Fehler:
terminate called after throwing an instance of 'std::out_of_range'
what(): basic_string::eraseDas bedeutet ja, dass ich im String eine Position löschen will, die gar nicht existiert.
Zum Beipsiel:
string wort = "auto";
auto.erase(0,9);Hier würde ich neun Positionen löschen wollen, obwohl das Wort nur vier hat.
In großen Programmen (häufiges nutzen von erase) ist es aber schwierig die Stelle zu finden, die den Fehler verursacht.
Gibt es da irgendwelche anderen Möglichkeiten den Fehler (automatisch) suchen zu lassen oder geht dies nur manuell?
-
#include <string> #include <iostream> #include <exception> using namespace std; int main() { try { throw exception("blubbs"); } catch(exception &e) { cout << "exception catched in line" << __LINE__ << " of file " << __FILE__; } }
-
Wie wirkt sich dies denn dann auf mein Programm aus?
Läuft dies dann im Falle einer Exception weiter?
Was passiert mit der Anweisung, die etwas "erasen" sollte?
Wird diese ignoriert?Sorry, für die Frage, aber Programmiere noch nicht so lange.
Ich weiss zwar, dass es sowas gibt, aber verwendet habe ich die noch nie.
-
Berndoni schrieb:
ich erhalte beim Ausführen meines Programms den folgenden Fehler:
terminate called after throwing an instance of 'std::out_of_range'
what(): basic_string::eraseDas bedeutet ja, dass ich im String eine Position löschen will, die gar nicht existiert.
Zum Beipsiel:
string wort = "auto";
auto.erase(0,9);Hier würde ich neun Positionen löschen wollen, obwohl das Wort nur vier hat.
Der Aufruf ist völlig ok. Hier würde keine Exception geworfen werden. string::erase wirft nur eine Exception, wenn die Startposition ungültig ist. Also der erste Parameter "out of range ist". Der zweite Parameter bedeutet: "Anzahl der zu löschenden Zeichen". Ist der zweite Parameter größer als string::length - startPos, wird er automatisch auf string::length - startPos reduziert.
Zu deinem eigentlichen Problem:
Gibt es da irgendwelche anderen Möglichkeiten den Fehler (automatisch) suchen zu lassen oder geht dies nur manuell?
Das einfachste ist den Fehler gar nicht erst auftreten zu lassen, z.B. in dem du vor dem erase erstmal prüfst, ob die Startposition gültig ist. Ansonsten bist du auf die Mithilfe deines Compilers/Debuggers angewiesen. Moderne Entwicklungsumgebungen liefern dir zu jeder Exception einen Stacktrace, mit dem du bequem zur Wurfstelle navigieren kannst.
-
Wie teste ich denn am Besten, ob die Startposition gültig ist?
-
Erste mir einfallende Lösung wäre die behandlung des Fehlers per Exception. Die Funktion erase wirft, wie die Ausgaben der Applikationen sagen, eine Exception vom Typ out_of_range. [1] Die Exception kannst du so abfangen...
#include <iostream> #include <string> #include <stdexcept> using namespace std; int main() { string v = "auto"; try { v.erase(0,9); } catch(out_of_range) { cerr << "range error" << endl; } cout << v << endl; }
[1] Bei mir wird keine Exception geworfen. Auch die Verwendung von catch (...) spring nicht an. Womöglich sind das implementierungsspezifische Unterschiede. Ich gehe davon aus, dass die Funktion erase einen RangeCheck enthällt.
Edit: Haben wohl wärend ich geschrieben habe schon einige User geantwortet
-
Stichwort Debugger, eine nichtgefangene Exception landet im Call Stack normalerweise an der Stelle wo sie geworfen wird...
(Kennt heutzutage eigentlich kaum noch jemand Debugger?)
-
Berndoni schrieb:
Wie teste ich denn am Besten, ob die Startposition gültig ist?
Indem du sie vorher mit der Länge des Strings vergleichst.
if (startPos > deinString.length()) { // FEHLER! Tot und Verderben } else { // OK. deinString.erase(startPos, endPos); }
-
Um beim gdb die Ursache einer Exception festzustellen, benutzt man am besten den Befehl "catch throw". Damit läßt jede geworfene Exception das Programm anhalten.
-
Kann man mit Hilfe von Exceptions oder anderer Hilfsmittel auch Endlosschleifen verhindern?
-
wenn du hingehst und eine exception wirfst, wenn die bedingung, welche eine endlosschleife produzieren würde, könntest du dies vermeiden. Von der Verwendung des Konzept der Exceptions als Strukturbefehlen (Schleifen, etc.) ist aber abzuraten
-
HumeSikkins schrieb:
Berndoni schrieb:
Wie teste ich denn am Besten, ob die Startposition gültig ist?
Indem du sie vorher mit der Länge des Strings vergleichst.
if (startPos > deinString.length()) { // FEHLER! Tot und Verderben } else { // OK. deinString.erase(startPos, endPos); }
Bei startPos == deinString.length() ist auch noch Tod und Verderben.
-
Was nutzt ihr denn für Hilfsmittel gegen Endlosschleifen?
Oder verlasst ihr euch nur auf eure Erfahrung?
-
Man muss einfach nur garantieren, dass es eine Abbruchbedingung gibt.
-
Michael E. schrieb:
Man muss einfach nur garantieren, dass es eine Abbruchbedingung gibt.
Und falls diese falsch ist, hilft dir dein Debugger und wenn du nicht weißt wie der funktioniert, dann lern diesen erst kennen und arbeite dann weiter.
-
Ich würde keine Angst vor Endlosschleifen haben. Genauso wie Deadlocks keine Angst einflößen. Wenn sie auftreten, dann merkt man das schon und kann sie dann beheben.
Im normalen Programmieralltag kommen beide Fälle so selten vor, dass man da nichts spezielles gegen unternehmen muss.
-
Michael E. schrieb:
HumeSikkins schrieb:
Berndoni schrieb:
Wie teste ich denn am Besten, ob die Startposition gültig ist?
Indem du sie vorher mit der Länge des Strings vergleichst.
if (startPos > deinString.length()) { // FEHLER! Tot und Verderben } else { // OK. deinString.erase(startPos, endPos); }
Bei startPos == deinString.length() ist auch noch Tod und Verderben.
Nö. Ich habe vorher extra in den Standard geschaut und da steht (21.3.5.5)
Requires: pos <= size()
Throws: out_of_range if pos > size()
-
Berndoni schrieb:
Was nutzt ihr denn für Hilfsmittel gegen Endlosschleifen?
Ideen aus der formalen Programmverifikation wie z.B. Loop-Invarianten.
-
lucky_tux schrieb:
string v = "auto"; try { v.erase(0,9); } catch(out_of_range) { cerr << "range error" << endl; }
Sorry, aber das ist ja nun wirklich mal schlecht!
Wenn, dann schon richtig:
catch(const out_of_range &e) { cerr << e.what() << endl; }
-
Wirft eigentlich jede Methode der Klasse String seine eigene Exception?
Also werfen erase, replace, usw. alle:
terminate called after throwing an instance of 'std::out_of_range'
what(): basic_string::erase