„Wenn ein Arbeiter seine Arbeit gut machen will, muss er zuerst seine Werkzeuge schärfen.“ – Konfuzius, „Die Gespräche des Konfuzius. Lu Linggong“
Titelseite > Programmierung > Lauert undefiniertes Verhalten in der std::string-Verkettung im Code von Bjarne Stroustrup?

Lauert undefiniertes Verhalten in der std::string-Verkettung im Code von Bjarne Stroustrup?

Veröffentlicht am 11.11.2024
Durchsuche:570

Does Undefined Behavior Lurk in std::string Chaining in Bjarne Stroustrup\'s Code?

Zeigt der Verkettungsausdruck von std::string in Bjarne Stroustrups Code undefiniertes Verhalten?

In Bjarne Stroustrups „The C Programming Language“, 4. Auflage , ein Codeausschnitt veranschaulicht die Verkettung mithilfe des Ersetzens von std::string Methode:

void f2() {
    std::string s = "but I have heard it works even if you don't believe in it";
    s.replace(0, 4, "").replace(s.find("even"), 4, "only").replace(s.find(" don't"), 6, "");

    assert(s == "I have heard it works only if you believe in it");
}

Dieser Code zeigt jedoch nicht spezifiziertes Verhalten, anstatt undefiniertes Verhalten aufzurufen.

Der Grund für dieses nicht spezifizierte Verhalten liegt in der Reihenfolge der Auswertung, die nicht spezifiziert ist Unterausdrücke verketteter Funktionsaufrufe. In diesem Fall werden die s.find-Funktionsaufrufe entweder vor oder nach dem ersten s.replace-Aufruf ausgewertet, wodurch die Länge der resultierenden Zeichenfolge geändert und das Ergebnis des nachfolgenden find-Aufrufs beeinflusst wird.

Das Beispiel in der Frage zeigt dies: Bei der Auswertung durch verschiedene Compiler (Clang, GCC) werden aufgrund der unterschiedlichen Auswertung unterschiedliche Ergebnisse erzielt Aufträge.

Details

Funktionsargumente haben eine nicht spezifizierte Auswertungsreihenfolge, und während die Verkettung von Funktionsaufrufen eine Auswertungsreihenfolge von links nach rechts für jeden Funktionsaufruf einführt, die Argumente jedes Aufrufs werden vor nur in Bezug auf diesen bestimmten Funktionsaufruf sequenziert.

Im Beispiel entsteht diese Unbestimmtheit in der Auswertung von s.find("even") und s.find(" don't") in Bezug auf s.replace(0, 4, "").

Unter Ignorierung weiterer Unterausdrucksaufschlüsselungen wird die Die Reihenfolge der Bewertungsschritte und ihre gegenseitige Abhängigkeit können wie folgt dargestellt werden:

Step 1: s.replace(0, 4, "")  // A
Step 2: s.find("even")       // B
Step 3: s.replace(B, 4, "only") // C
Step 4: s.find("don't")      // D
Step 5: s.replace(D, 6, "")   // E

Während A vor B sequenziert wird, das wiederum vor C sequenziert wird, gibt es keine Sequenzierungsbeziehung zwischen B und D in Bezug auf A. Daher kann D entweder vor oder nach A ausgewertet werden, was je nach gewählter Reihenfolge zu unterschiedlichen Ergebnissen führt.

C 17 Änderungen

Der C 17-Standard stärkt die Reihenfolge der Bewertungsregeln für Postfix-Ausdrücke und ihre Ausdrucksliste und verleiht dem betreffenden Code ein klar spezifiziertes Verhalten. Die Reihenfolge ist wie folgt:

  • Der Postfix-Ausdruck wird vor jedem Ausdruck in der Ausdrucksliste sequenziert.
  • Die Initialisierung jedes Parameters ist in Bezug auf die aller anderen Parameter unbestimmt sequenziert anderer Parameter.

Daher wird dieser Code in C 17 und höher immer korrekt ausgewertet.

Freigabeerklärung Dieser Artikel wird unter folgender Adresse abgedruckt: 1729674849 Bei Verstößen wenden Sie sich bitte an [email protected], um ihn zu löschen
Neuestes Tutorial Mehr>

Haftungsausschluss: Alle bereitgestellten Ressourcen stammen teilweise aus dem Internet. Wenn eine Verletzung Ihres Urheberrechts oder anderer Rechte und Interessen vorliegt, erläutern Sie bitte die detaillierten Gründe und legen Sie einen Nachweis des Urheberrechts oder Ihrer Rechte und Interessen vor und senden Sie ihn dann an die E-Mail-Adresse: [email protected] Wir werden die Angelegenheit so schnell wie möglich für Sie erledigen.

Copyright© 2022 湘ICP备2022001581号-3