Ist ein Programm, das niemals ein gültiges C ++ - Programm beendet?

15

Muss ein Programm beendet werden? Mit anderen Worten, ist ein Programm, das für immer technisch undefiniertes Verhalten läuft? Beachten Sie, dass es hier nicht um leere Schleifen geht. Apropos Programme, die für immer "Zeug" (dh beobachtbares Verhalten) tun.

ZB so etwas:

int main()
{
    while (true)
    {
        try
        {
            get_input(); // calls IO
            process();
            put_output(); // calls IO, has observable behavior

            // never break, exit, terminate, etc
        } catch(...)
        {
            // ignore all exceptions
            // don't (re)throw
            // never go out of loop
        }
    }
}

Dies ist eher eine akademische Frage, da empirisch alle vernünftigen Compiler den erwarteten Code für die oben genannte Art von Programm generieren (vorausgesetzt natürlich keine andere UB-Quelle). Und ja, natürlich gibt es viele Programme, die niemals beendet werden (Betriebssystem, eingebettet, Server). Allerdings ist der Standard manchmal skurril, daher die Frage.


Tangential: Viele (einige?) Definitionen von "Algorithmus" erfordern, dass ein Algorithmus beendet werden muss , dh eine Reihe von Operationen, die niemals beendet werden, werden nicht als Algorithmus betrachtet.


Tangential. Das Stoppproblem besagt, dass es keinen Algorithmus geben kann, um zu bestimmen, ob ein beliebiges Programm für eine Eingabe beendet wird. Da es jedoch für dieses spezielle Programm keinen Zweig gibt, der zum Verlassen von main führt, kann der Compiler leicht bestimmen, dass das Programm niemals enden wird. Dies ist jedoch irrelevant, da es sich um einen Sprachanwalt handelt.

Bolov
quelle
Kommentare sind nicht für eine ausführliche Diskussion gedacht. Dieses Gespräch wurde in den Chat verschoben .
Samuel Liew

Antworten:

15

Der C ++ - Standard enthält nichts, was das Beenden des Programms oder eines bestimmten Threads erfordert. Das, was dem am nächsten kommt, ist [intro.progress] p1 , das sagt

Die Implementierung kann davon ausgehen, dass ein Thread möglicherweise einen der folgenden Schritte ausführt:

  • beenden,
  • eine Bibliotheks-E / A-Funktion aufrufen,
  • Führen Sie einen Zugriff über einen flüchtigen Wert durch, oder
  • Führen Sie eine Synchronisationsoperation oder eine atomare Operation durch.

[  Hinweis: Dies soll Compiler-Transformationen wie das Entfernen leerer Schleifen ermöglichen, auch wenn die Beendigung nicht nachgewiesen werden kann. -  Endnote  ]

Solange irgendwann ein beobachtbares Verhalten vorliegt oder die gesamte Zeit für eine E / A-Operation oder einen anderen blockierenden Bibliotheksaufruf blockiert ist, gilt dies nicht und das Programm ist gültig (vorausgesetzt, es erfüllt alle Anforderungen andere Gültigkeitskriterien).

Daniel H.
quelle
"eine E / A-Operation oder ein anderer blockierender Bibliotheksaufruf" - der Standard ist ziemlich klar und listet nur E / A-Operationen auf. Warum fügen Sie "oder einen anderen blockierenden Bibliotheksaufruf" hinzu? Auch die I / O - Operation ist bereits in der früheren „enthält einige beobachtbare Verhalten“.
MSalters
1
@MSalters std::mutex::lock()ist ein Bibliotheksaufruf, bei dem es sich um eine Synchronisierungsoperation handelt, die unter den vierten Punkt fällt. Es ist also nicht wahr, dass nur E / A-Anrufe erwähnt werden.
Igor Tandetnik
Wenn es bei der Eingabe hängen bleibt , aber keine bekommt, ist es fraglich, ob dies als beobachtbar gilt.
Daniel H
4

Ja. Von[intro.progress]

Die Implementierung kann davon ausgehen, dass ein Thread möglicherweise einen der folgenden Schritte ausführt:

  • beenden,
  • eine Bibliotheks-E / A-Funktion aufrufen,
  • Führen Sie einen Zugriff über einen flüchtigen Wert durch, oder
  • Führen Sie eine Synchronisationsoperation oder eine atomare Operation durch.

[ Hinweis: Dies soll Compiler-Transformationen wie das Entfernen leerer Schleifen ermöglichen, auch wenn die Beendigung nicht nachgewiesen werden kann. - Endnote ]

Caleth
quelle
Ich glaube, eine kleine Beschreibung, die besagt, dass das Programm E / A ausführt, wäre ratsam.
KamilCuk
Solange das get_inputund die put_outputFunktionen im OPs-Beispiel "Aufruf einer Bibliotheks-E / A-Funktion" ist, sollte das Programm auch dann gültig sein, wenn es nicht beendet wird?
Einige Programmierer Typ
@Someprogrammerdude oder Zugriff auf einen flüchtigen oder atomaren Wert, Ja
Caleth
neugierig auf den Pre-C ++ 11-Standard, als es nicht das aktuelle Speichermodell gab.
Bolov
1
compiler does not know- Das ist irrelevant. Der Compiler kann es aus Sicht der Sprachebene wissen und nicht wissen - die Frage ist, ob es auf jeden Fall gültig ist.
KamilCuk