Was genau ist die Als-ob-Regel?

88

Wie der Titel sagt,

Was genau ist die "Als ob" -Regel?

Eine typische Antwort wäre:

Die Regel, die alle Codetransformationen zulässt, die das beobachtbare Verhalten des Programms nicht ändern

Von Zeit zu Zeit erhalten wir Verhaltensweisen von bestimmten Implementierungen, die dieser Regel zugeordnet sind. Viele Male falsch. Also, was genau ist diese Regel. In der Norm wird diese Regel nicht eindeutig als Abschnitt oder Absatz erwähnt. Was fällt also genau in den Geltungsbereich dieser Regel? Für mich scheint es eine Grauzone zu sein, die vom Standard nicht im Detail definiert wird. Kann jemand die Details unter Berufung auf die Referenzen aus dem Standard näher erläutern?

Hinweis: Kennzeichnen Sie dies als C und C ++, da es für beide Sprachen relevant ist.

Alok Speichern
quelle
2
Es bezieht sich auf die abstrakte Maschine.
Alexey Frunze
" Kennzeichnen Sie dies als C und C ++, da es für beide Sprachen relevant ist." Es ist in jeder Sprache relevant.
Neugieriger
@AlexeyFrunze " Es bezieht sich auf die abstrakte Maschine " Es bezieht sich darauf, dass der Zustand der "abstrakten Maschine" ein Werkzeug und kein Ende ist und hinsichtlich der Konformität irrelevant ist, weil es "abstrakt" ist, das ein nicht reales Spezifikationswerkzeug ist.
Neugieriger

Antworten:

98

Was ist die " als ob " -Regel?

Die " Als-ob " -Regel definiert grundsätzlich, welche Transformationen eine Implementierung in einem legalen C ++ - Programm ausführen darf. Kurz gesagt, alle Transformationen, die das " beobachtbare Verhalten " eines Programms nicht beeinflussen (siehe unten für eine genaue Definition), sind zulässig.

Ziel ist es, Implementierungen die Freiheit zu geben, Optimierungen durchzuführen, solange das Verhalten des Programms mit der vom C ++ - Standard in Bezug auf eine abstrakte Maschine festgelegten Semantik übereinstimmt.


Wo führt der Standard diese Regel ein?

Der C ++ 11 Standard führt die " Als-ob " -Regel in Abschnitt 1.9 / 1 ein:

Die semantischen Beschreibungen in dieser Internationalen Norm definieren eine parametrisierte nichtdeterministische abstrakte Maschine. Diese Internationale Norm stellt keine Anforderungen an die Struktur konformer Implementierungen. Insbesondere müssen sie die Struktur der abstrakten Maschine nicht kopieren oder emulieren. Vielmehr sind konforme Implementierungen erforderlich, um (nur) das zu emulieren beobachtbare Verhalten der abstrakten Maschine wie nachstehend erläutert.

Eine erklärende Fußnote fügt hinzu:

Diese Bestimmung wird manchmal als "Als-ob" -Regel bezeichnet , da eine Implementierung frei ist, eine Anforderung dieser Internationalen Norm zu ignorieren, solange das Ergebnis so ist, als ob die Anforderung eingehalten worden wäre, soweit sich aus dem beobachtbaren Verhalten ergibt des Programms. Beispielsweise muss eine tatsächliche Implementierung keinen Teil eines Ausdrucks bewerten, wenn daraus geschlossen werden kann, dass sein Wert nicht verwendet wird und keine Nebenwirkungen auftreten, die das beobachtbare Verhalten des Programms beeinflussen.


Was genau schreibt die Regel vor?

In Absatz 1.9 / 5 wird ferner Folgendes festgelegt:

Eine konforme Implementierung , die ein wohlgeformtes Programm ausführt, muss dasselbe beobachtbare Verhalten erzeugen wie eine der möglichen Ausführungen der entsprechenden Instanz der abstrakten Maschine mit demselben Programm und derselben Eingabe . Wenn eine solche Ausführung jedoch eine undefinierte Operation enthält, stellt diese Internationale Norm keine Anforderung an die Implementierung, die dieses Programm mit dieser Eingabe ausführt (nicht einmal in Bezug auf Operationen, die der ersten undefinierten Operation vorausgehen).

Es ist hervorzuheben, dass diese Einschränkung nur beim "Ausführen eines wohlgeformten Programms" gilt und dass die möglichen Ergebnisse der Ausführung eines Programms, das undefiniertes Verhalten enthält, nicht eingeschränkt sind. Dies wird auch in Absatz 1.9 / 4 explizit ausgeführt:

Bestimmte andere Operationen werden in dieser Internationalen Norm als undefiniert beschrieben (z. B. der Effekt des Versuchs, ein const-Objekt zu ändern). [Hinweis: Diese Internationale Norm stellt keine Anforderungen an das Verhalten von Programmen, die undefiniertes Verhalten enthalten . - Endnote]

In Bezug auf die Definition von " beobachtbarem Verhalten " lautet Ziffer 1.9 / 8 schließlich wie folgt:

Die geringsten Anforderungen an eine konforme Implementierung sind:

- Der Zugriff auf flüchtige Objekte wird streng nach den Regeln der abstrakten Maschine bewertet.

- Bei Programmbeendigung müssen alle in Dateien geschriebenen Daten mit einem der möglichen Ergebnisse identisch sein, die die Ausführung des Programms gemäß der abstrakten Semantik ergeben hätte.

- Die Eingabe- und Ausgabedynamik interaktiver Geräte muss so erfolgen, dass die Aufforderung tatsächlich ausgegeben wird, bevor ein Programm auf die Eingabe wartet. Was ein interaktives Gerät ausmacht, ist implementierungsdefiniert.

Diese werden zusammen als beobachtbares Verhalten des Programms bezeichnet . [ Hinweis : Jede Implementierung kann strengere Entsprechungen zwischen abstrakter und tatsächlicher Semantik definieren. - Endnote ]


Gibt es Situationen, in denen diese Regel nicht gilt?

Nach meinem besten Wissen ist die einzige Ausnahme von der " Als-ob " -Regel die Kopier- / Verschiebungselision, die zulässig ist, obwohl der Kopierkonstruktor, der Verschiebungskonstruktor oder der Destruktor einer Klasse Nebenwirkungen haben. Die genauen Bedingungen hierfür sind in Abschnitt 12.8 / 31 angegeben:

Wenn bestimmte Kriterien erfüllt sind, kann eine Implementierung die Kopier- / Verschiebungskonstruktion eines Klassenobjekts weglassen, selbst wenn der für die Kopier- / Verschiebungsoperation ausgewählte Konstruktor und / oder der Destruktor für das Objekt Nebenwirkungen haben . [...]

Andy Prowl
quelle
2
Ich habe dieses Zitat gesehen. Was nicht klar ist, ist die Definition von beobachtbarem Verhalten. Was genau ist ein beobachtbares Verhalten? Die Kopierentscheidung als Ausnahme von der Als-ob-Regel ist ziemlich bekannt und nicht wirklich Teil meiner Frage.
Alok Save
2
@AlokSave: Nun, im C-Standard sehen wir "Der Zugriff auf ein flüchtiges Objekt, das Ändern eines Objekts, das Ändern einer Datei oder das Aufrufen einer Funktion, die eine dieser Operationen ausführt, sind alles Nebenwirkungen". Vermutlich gibt es etwas Äquivalentes in den C ++ - Standards. Informell denke ich, "alles, was seine Interaktion mit der Außenwelt verändert".
Oliver Charlesworth
1
Jedes Verhalten, das den Status der abstrakten Maschine ändert (also etwas, das eine übergebene Variable oder eine globale Variable ändert oder E / A-Geräte liest und in diese schreibt).
Mats Petersson
1
Bedeutet dies, dass das Löschen einer Endlosschleife, die nichts tut, erlaubt ist, solange danach nichts Beobachtbares passiert?
Harold
5
Besonders zu beachten ist, dass dies nur für Rechtsprogramme gilt . Alles, was undefiniertes Verhalten hervorruft, wird ausdrücklich nicht erfasst.
vonbrand
15

In C11 wird die Regel niemals mit diesem Namen aufgerufen. C definiert jedoch genau wie C ++ das Verhalten in Bezug auf abstrakte Maschinen. Die Als-ob-Regel ist in C11 5.1.2.3p4 und p6 :

  1. In der abstrakten Maschine werden alle Ausdrücke gemäß der Semantik ausgewertet. Eine tatsächliche Implementierung muss keinen Teil eines Ausdrucks auswerten, wenn daraus geschlossen werden kann, dass sein Wert nicht verwendet wird und keine erforderlichen Nebenwirkungen auftreten (einschließlich solcher, die durch den Aufruf einer Funktion oder den Zugriff auf ein flüchtiges Objekt verursacht werden).

  2. [...]

  3. Die geringsten Anforderungen an eine konforme Implementierung sind:

    • Zugriffe auf volatileObjekte werden streng nach den Regeln der abstrakten Maschine ausgewertet.
    • Bei Beendigung des Programms müssen alle in Dateien geschriebenen Daten mit dem Ergebnis identisch sein, das die Ausführung des Programms gemäß der abstrakten Semantik ergeben hätte.
    • Die Eingangs- und Ausgangsdynamik interaktiver Geräte muss gemäß 7.21.3 erfolgen . Mit diesen Anforderungen soll beabsichtigt werden, dass die ungepufferte oder zeilengepufferte Ausgabe so schnell wie möglich angezeigt wird, um sicherzustellen, dass tatsächlich Aufforderungsnachrichten angezeigt werden, bevor ein Programm auf die Eingabe wartet.

     

    Dies ist das beobachtbare Verhalten des Programms.

Antti Haapala
quelle
-1

In C, C ++, Ada, Java, SML ... in jeder Programmiersprache, die durch Beschreibung des (normalerweise vielen möglichen, nicht deterministischen) Verhaltens eines Programms (das einer Reihe von Interaktionen an E / A-Ports ausgesetzt ist) genau spezifiziert ist. , gibt es keine eindeutige as-if - Regel .

Ein Beispiel für eine eindeutige Regel ist die, die besagt, dass eine Division durch Null eine Ausnahme auslöst (Ada, Caml) oder eine Null-Dereferenzierung eine Ausnahme auslöst (Java). Sie könnten die Regel ändern, um etwas anderes anzugeben, und Sie würden eine andere Sprache erhalten (die manche Leute lieber als "Dialekt" (*) bezeichnen würden. Eine bestimmte Regel dient dazu, bestimmte Verwendungen einer Programmiersprache wie eine bestimmte anzugeben Die grammatikalischen Regeln decken einige Syntaxkonstrukte ab.

(*) Ein Dialekt ist nach Ansicht einiger Linguisten eine Sprache mit einer "Armee". In diesem Zusammenhang könnte dies eine Programmiersprache ohne ein Komitee und eine bestimmte Branche von Compiler-Editoren bedeuten.

Die Als-ob-Regel ist keine eindeutige Regel . Es deckt kein bestimmtes Programm ab und ist nicht einmal eine Regel, die diskutiert, entfernt oder auf irgendeine Weise geändert werden könnte : Die sogenannte "Regel" wiederholt lediglich, dass die Programmsemantik definiert ist und nur portabel (universell) sein kann. definiert in Bezug auf die sichtbaren Wechselwirkungen einer Ausführung des Programms mit der "externen" Welt.

Die Außenwelt kann E / A-Schnittstellen (stdio), eine grafische Benutzeroberfläche oder sogar ein interaktiver Interpreter sein, der den resultierenden Wert einer reinen Anwendungssprache ausgibt. In C und C ++ sind die (vage angegebenen) Zugriffe auf flüchtige Objekte enthalten. Dies ist eine andere Möglichkeit zu sagen, dass einige Objekte an einem bestimmten Punkt streng nach dem ABI (Application Binary Interface) im Speicher dargestellt werden müssen, ohne das ABI jemals explizit zu erwähnen.

Die Definition einer Ausführungsspur , auch sichtbares oder beobachtbares Verhalten genannt, definiert, was unter "Als-ob-Regel" zu verstehen ist. Die Als-ob-Regel versucht es zu erklären, aber auf diese Weise verwirrt sie die Menschen mehr als sie die Dinge klärt, da sie den Ausdruck einer zusätzlichen semantischen Regel gibt, die der Implementierung mehr Spielraum gibt.

Zusammenfassung:

  • Die sogenannte "Als-ob-Regel" lockert keine Einschränkungen für Implementierungen.
  • Sie können die Als-ob-Regel in keiner Programmiersprache entfernen, die im Hinblick auf sichtbares Verhalten angegeben ist (Ausführungsspuren, die für die Interaktion mit der Außenwelt erstellt wurden), um einen eindeutigen Dialekt zu erhalten.
  • Sie können die Als-ob-Regel keiner Programmiersprache hinzufügen, die nicht im Hinblick auf das sichtbare Verhalten angegeben ist.
Neugieriger
quelle
Wenn die Leute glauben, dass ich falsch liege und es eine eindeutige "Als ob-Regel" gibt, warum versuchen sie dann nicht, eine Variante von C ++ (einen Dialekt) ohne diese "Regel" zu beschreiben? Was würde die C ++ - Spezifikation ohne sie überhaupt bedeuten? Es ist absolut unmöglich zu sagen, ob ein Compiler konform ist. Oder sogar konform zu definieren.
Neugieriger