Unerklärliche out_of_range in string::substr
Habe ich immer eine wirklich lästige Fehler über eine std::out_of_range bei Aufruf der substr. Der genaue Fehler ist
kündigen, genannt nach dem werfen ein
instance of 'std::out_of_range'
what(): basic_string::substr
Ich bin absolut sicher, dass tmp_request hat eine Länge größer als 1. Egal was ich pass auf substr—1, 2, oder bodypos—es wirft immer diesen Fehler. Ich bin mit g++ auf Unix.
Einzige interessante Sache, die ich einschließen kann, ist der string hat mehrere "\r\n"
, darunter eine "\r\n\r\n"
.
In einer cpp-Datei:
std::string tmp_request, outRequest;
tmp_request = SS_Twitter->readData();
outRequest = SS_Twitter->parse(tmp_request);
In einem anderen:
std::string parse(const std::string &request)
{
std::map<std::string,std::string> keyval;
std::string outRequest;
if(request[0]=='P')
{
if(request.find("register")!=std::string::npos)
{ //we have a register request
size_t bodypos = request.find("username");
if(bodypos==std::string::npos)
{
HttpError(400,"Malformed HTTP POST request. Could not find key username.",request);
}
else
{
std::string body = request.substr(bodypos);
StringExplode(body,"&", "=",keyval);
outRequest = "doing stuff";
}
}
Update:
std::string request2("P\r\nregister\r\nusername=hello\r\n\r\n");
std::string body = request2.substr(4);
Wirft den gleichen Fehler. Jetzt weiß ich, das ist absolut gültigen und korrekten code, aber es ist immer noch wirft den Fehler.
//entfernt Quelle-link
- Ok der code ist zwar nicht sauber. Aber konzentrieren wir uns auf die Fehler bitte?
- Ob oder ob nicht etwas ist ein bug der selten eine Meinung, wenn es um Sprache geht. Sollten Sie bezweifle, dass eine solche primitive Funktion hat einen bug in der Implementierung, da Sie sonst verfangen Sie sich auf die falsche Sache. Die Tatsache, Sie halten beibehalten Ihren code richtig ist und die Umsetzung ist irgendwie falsch, wird nie Ihr problem lösen. Offensichtlich haben Sie einen logischen Fehler irgendwo; Sie müssen die lassen Sie Ihre Annahmen und starten Sie frisch.
- Haben Sie versuchen, Ihren code sauber, und sehen, ob Fehler erneut Auftritt? Vielleicht das der Grund.
- Das ist falsch:
if(int(request.find("register"))!=std::string::npos)
.npos
ist einsize_t
, eine vorzeichenlose Ganzzahl, währendint
ist eine vorzeichenbehaftete Ganzzahl. Es gibt keine Notwendigkeit zu werfen das Ergebnis derfind
, und alles, was Sie tun, ist das hacken der Bereich in der Mitte. In der Tat, werden Sie immer geben diese if-Anweisung, da einint
wahrscheinlich niemals erreichen können, die maximale Wert einersize_t
(wasnpos
ist). Wenn es nicht der Fehler, es ist ein bug. - Ich würde vorschlagen, die Protokollierung der Länge von
request
und der Wert derbodypos
. Das wird Ihnen mit Sicherheit sagen, ob Sie sehen, schlechte Verhalten vonsubstr
oder ob Sie bestanden in der schlechten Argumente. - Ich habe log die Länge und den Wert von request den Wert des bodypos. Aber es ist egal. Auch wenn ich den pass substr(2), es wird mir dieser Fehler. Die Länge der Zeichenfolge angemeldet ist immer um 150.
- In Ergänzung zu meinem letzten Kommentar, das ist auch falsch:
int bodypos = request.find("username");
Wieder, bist du hacken das Angebot in der Hälfte, und wird nie geben Sie die nachfolgende if-Anweisung. Ich denke, das sollte entstehen, eine Warnung; verwandeln Sie Ihren warn-levels zu sehen. - Ich verstehe, dass einige von Euch vielleicht Sache, ich habe eine vorgefasste Idee, dass der Fehler hier passiert, aber getestet habe ich diese alle über den Ort, einschließlich in einem anderen Programm. Nicht schätzen, einige der negativen Bemerkungen.
- Ok, ich werde drehen Sie die Warnungen auf und versuchen mit size_t bodypos. Update: dasselbe.
- Sollten Sie Ihren code anzupassen, dann, damit die Leute wissen, was Sie versucht haben, und dass der code verbessert wird.
- Palatnik: Sie sollten nicht versuchen, "size_t bodypos". Sollten Sie verwenden
std::string::size_type bodypos
. - Ok werde ich verwenden, size_type. Gleiche Fehler.
- Ich bin mir ziemlich sicher, dass
std::string::size_type
ist immersize_t
. Es ist die Zuweisung dersize_type
, die die Standard-Zuweisung, wer istsize_type
istsize_t
. - Das einzige mal, dass ich gesehen habe, einen mysteriösen "bug" in einem string-Methode (oder in einem anderen Ort, wo nichts könnte möglicherweise falsch sein), es hatte zu tun mit nicht verwandten Undefiniertes Verhalten an anderer Stelle im Programm.
- Durch die Art und Weise, die \r\n ist ein Ablenkungsmanöver, wenn Sie denken, dass es komprimiert \n - nur für I/O (und nur unter bestimmten Umständen auf einigen Plattformen, wenn Sie öffnen Sie die Dateien im text-Modus, auf einem neuen Mond, etc.).
- Ich bin mir nicht sicher, warum Menschen downvote diese Frage. Es ist legitim code mit einem legitimen problem, lassen Sie uns helfen, den Kerl zu finden und zu bereinigen, unsere Antworten, so dass Sie anderen helfen, die vielleicht ähnliche Probleme.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Modifizierte ich dein Beispiel etwas zu verringern Anzahl an Einrückungen verwendet.
Es gibt 5 "test cases" und keine Ursachen problemlos. Könnten Sie bitte geben Sie eine Probe fordern, um das problem reproduzieren, das Sie haben.
EDIT: Vergessen zu erwähnen: wenn dieses Beispiel-wie es ist (mit auskommentierten bits) produziert nicht den Fehler, Ihre beste Wette ist, dass Sie einen Fehler in Ihrem
StringExplode
Funktion. Sie konnte nach der Quelle, um eine weitere hilfreiche Ratschläge.EDIT2:
In Ihrem
StringExplode
ändernresults[tmpKey] = tmpKey.substr(found+1);
zuresults[tmpKey] = tmpResult[i].substr(found+1);
. Ändernint found
zusize_t found
, und entfernen Sie alleif (found > 0)
, das wird beheben Ihre geheimnisvolle out_of_range. Sie warensubstr
-ing eine falsche Zeichenkette. Just in case, hier ist der code mit einem Update:Erster test-code:
Diese Ausgänge, vorhersagbar:
StringExplode
? Wahrscheinlich ist der bug da.::std::string::size_t
, nicht nursize_t
.Sind Sie sicher, dass es andernfalls auf, dass
substr
und nicht auf einesubstr
Aufruf innerhalb derHttpError
oderStringExplode
Funktionen? Wenn Sie nicht bereits getan haben, führen Sie diesen durch einen debugger, so dass Sie genau sehen können, wo es wirft die Ausnahme. Alternativ könnte man hinzufügen:Zeile, unmittelbar bevor Sie anrufen
substr
, und eine ähnliche Linie unmittelbar danach, so dass es Aussehen würde:Wenn das
substr
ist wirklich das werfen der exception, dann wirst du wissen, weil das Programm print "Aufruf von substr" ohne eine passende "fertige Aufruf von substr". Wenn es druckt die paar debug-Meldungen an, obwohl, oder gar keine, dann ist etwas anderes das werfen der Ausnahme.Eine ziemlich offensichtliche Sache falsch mit Ihrem code:
Sind Sie nicht checken, dass read () - gelang - es gibt -1 im Fehlerfall zurück, die bewirkt, dass alle Arten von Speicher Korruption Probleme, wenn es Auftritt.
Auch:
Du nimmst die Größe des Zeiger - Sie wollen die Länge der Ausgabe-string:
Und sollten Sie noch einmal testen, das schreiben erfolgreich war und, dass er schrieb so viele bytes, wie von Ihnen gewünscht, allerdings soll dies nicht direkt verursachen, die substr () - Fehler.
Sieht aus wie Sie brauchen ein anderes nach
sonst Sie rufen substr mit bodypos = npos
else
existiert, und (natürlich), bevor wir wussten, dassHttpError
würde verlassen Sie die Funktion. Eine gültige, aber jetzt irrelevante Antwort.Könnten Sie in Erwägung ziehen, die (unsigned) Typ
std::string::size_type
stattint
.Warum wirfst du das Ergebnis von find in eine int-hier:
int(request.find("register"))!=std::string::npos