2016-07-18 9 views
12

Sind noreturn Attribute auf nie wiederkehrende Funktionen notwendig, oder ist das nur ein (wohl zu frühes? - zumindest für Exits, kann ich mir nicht vorstellen, warum dort Optimierung optimieren)?Sind Noreturn-Attribute bei bestehenden Funktionen notwendig?

Es wurde mir erklärt, dass in einem Kontext wie

void myexit(int s) _Noreturn { 
    exit(s); 
} 
// ... 
if (!p) { myexit(1); } 
f(*p); 
/// ... 

noreturn verhindert, dass die !p Zweig von out optimiert. Aber ist es wirklich zulässig, dass ein Compiler diesen Zweig optimiert? Ich realisiere die Begründung für die Optimierung wäre: "Undefined Verhalten kann nicht passieren. Wenn == NULL, Dereferenzierung ist es UB, daher p kann nie NULL in diesem Zusammenhang sein, daher der !p Zweig nicht ausgelöst". Kann der Compiler das Problem nicht genauso gut lösen, indem er annimmt, dass myexit eine Funktion sein kann, die nicht zurückkehrt (auch wenn sie nicht explizit als solche gekennzeichnet ist)?

+0

Ich bin zögerlich, dieses C++ auch zu markieren, weil glücklich Puristen downvote, aber C++ hat noreturn Attribute ('[[noreturn]]') auch, und eine C/C++ Antwort wäre sehr willkommen. – PSkocik

+2

_ "noreturn verhindert, dass der'! P'-Zweig optimiert wird. "_ Why? – mvidelgauz

+0

Mögliches Duplikat - http://stackoverflow.com/questions/10538291/what-is-the-point-of-noreturn – mvidelgauz

Antwort

7

Dies ermöglicht mehrere Optimierungen. Erstens, für den Aufruf selbst kann dies eine vereinfachte Einrichtung ermöglichen, nicht alle Register müssen gespeichert werden, eine jmp Anweisung kann anstelle von call oder ähnlichem verwendet werden. Dann kann der Code nach dem Aufruf auch optimiert werden, da keine Verzweigung zum normalen Ablauf erfolgt.

Also ja, normalerweise _Noreturn ist eine wertvolle Information für den Compiler.

Aber als direkte Antwort auf Ihre Frage, nein, das ist eine Eigenschaft für die Optimierung, so ist es nicht erforderlich.

+2

Danke, aber das beantwortet die Frage nicht. – PSkocik

+1

@ PSkocik, siehe meine Bearbeitung. –

+1

@JensGustedt Es ist nicht sehr detailliert, aber zumindest beantwortet es jetzt den Hauptteil der Frage ;-) – PSkocik

2

Axiom: Der Standard ist die definitive Ressource auf, was gut definiert in C.

  • Die Norm legt assert daher assert mit wohldefiniert.
  • assert bedingt ruft abort, eine _Noreturn Funktion, also das ist erlaubt.
  • Jede Verwendung von assert ist in einer Funktion. Daher können Funktionen zurückkehren oder nicht.
  • Der Standard hat dieses Beispiel:

    _Noreturn void g (int i) { // causes undefined behavior if i <= 0 
        if (i > 0) abort(); 
    } 
    

    Daher bedingt Rückkehr Funktionen nicht _Noreturn sein muss. Das bedeutet:

    • Für extern definierten Funktionen hat der Compiler die Funktion übernehmen könnte nicht zurück und ist nicht frei, die if -branch
    • Für „intern“ definierten Funktionen zu optimieren, kann der Compiler prüfen Sie, ob die Funktion tatsächlich immer wieder zurückkehrt und den Zweig optimiert.

In beiden Fällen richten kompilierten Programmverhalten mit dem, was eine nicht-Optimierung abstrakte C Maschine tun würde und die ‚As-if‘ -Regel beobachtet wird.

+0

Dachte, es als Beweis zu schreiben wäre cool, jetzt schau es an, ich bin mir nicht mehr so ​​sicher. Aber es beantwortet die Frage, die ich denke. :-) Fühlen Sie sich frei, es zu bearbeiten, um es formeller zu machen. – a3f

+1

Ein Compiler kann nicht davon ausgehen, dass extern definierte Funktionen nicht zurückkehren; Stattdessen muss es bereit sein, sowohl die Fälle zu behandeln, in denen die Funktion zurückkehrt (Code, der der Funktion folgt, kann nicht weggelassen werden), als auch die Fälle, in denen die Funktion nicht ausgeführt werden kann (Code, der der Funktion folgt, kann die Ausführung der Funktion oder irgendetwas nicht beeinflussen) bevor). – supercat

+0

@supercat, umformatiert es. Vielen Dank. – a3f

Verwandte Themen