Heute haben wir die Ursache eines bösen Fehlers herausgefunden, der nur zeitweise auf bestimmten Plattformen auftrat. In Kürze sah unser Code so aus:
class Foo {
map<string,string> m;
void A(const string& key) {
m.erase(key);
cout << "Erased: " << key; // oops
}
void B() {
while (!m.empty()) {
auto toDelete = m.begin();
A(toDelete->first);
}
}
}
Das Problem könnte in diesem vereinfachten Fall offensichtlich sein: BÜbergibt einen Verweis auf den Schlüssel an A, der den Karteneintrag entfernt, bevor versucht wird, ihn zu drucken. (In unserem Fall wurde es nicht gedruckt, sondern komplizierter verwendet.) Dies ist natürlich undefiniertes Verhalten, da keyes sich nach dem Aufruf von um eine baumelnde Referenz handelt erase.
Dies zu beheben war trivial - wir haben nur den Parametertyp von const string&in geändert string. Die Frage ist: Wie hätten wir diesen Fehler überhaupt vermeiden können? Anscheinend haben beide Funktionen das Richtige getan:
Ahat keine Ahnung, waskeysich auf das bezieht, was zerstört werden soll.BSie hätten eine KopieAerstellen können, bevor Sie an sie weitergeleitet wurden , aber ist es nicht die Aufgabe des Anrufers, zu entscheiden, ob Parameter nach Wert oder nach Referenz verwendet werden sollen?
Gibt es eine Regel, die wir nicht befolgt haben?