Un programme qui ne termine jamais un programme C ++ valide?

15

Faut-il terminer un programme? En d'autres termes, un programme qui s'exécute pour toujours Comportement indéfini techniquement? Notez qu'il ne s'agit pas de boucles vides. Parler de programmes qui font des "trucs" (c'est-à-dire un comportement observable) pour toujours.

Par exemple quelque chose comme ça:

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
        }
    }
}

Il s'agit davantage d'une question académique, car empiriquement tous les compilateurs sensés généreront le code attendu pour le type de programme ci-dessus (en supposant bien sûr qu'aucune autre source d'UB). Et oui, bien sûr, il y a beaucoup de programmes qui ne se terminent jamais (os, embarqués, serveurs). Cependant, la norme est parfois excentrique, d'où la question.


Tangentiel: de nombreuses (certaines?) Définitions d '"algorithme" exigent qu'un algorithme se termine , c'est-à-dire qu'une série d'opérations qui ne se termine jamais n'est pas considérée comme un algorithme.


Tangentiel. Le problème d'arrêt indique qu'il ne peut pas exister d'algorithme pour déterminer si un programme arbitraire se termine pour une entrée. Cependant, pour ce programme particulier, car il n'y a pas de branche qui conduit à sortir du principal, le compilateur peut facilement déterminer que le programme ne se terminera jamais. Ceci n'est cependant pas pertinent car la question est la langue-avocat.

bolov
la source
Les commentaires ne sont pas pour une discussion approfondie; cette conversation a été déplacée vers le chat .
Samuel Liew

Réponses:

15

Il n'y a rien dans la norme C ++ qui oblige le programme, ou n'importe quel thread donné, à se terminer. La chose la plus proche de cela est [intro.progress] p1 , qui dit

L'implémentation peut supposer que n'importe quel thread finira par effectuer l'une des opérations suivantes:

  • mettre fin,
  • appeler une fonction d'E / S de bibliothèque,
  • effectuer un accès via une valeur gl volatile, ou
  • effectuer une opération de synchronisation ou une opération atomique.

[  Remarque: Ceci est destiné à permettre des transformations du compilateur telles que la suppression de boucles vides, même lorsque la terminaison ne peut pas être prouvée. -  note de fin  ]

Tant qu'il y a un comportement observable, éventuellement, ou tant qu'il passe tout son temps bloqué sur une opération d'E / S ou un autre appel de bibliothèque de blocage, cela ne s'applique pas et le programme est valide (en supposant qu'il rencontre tous les autres critères de validité).

Daniel H
la source
"une opération d'E / S ou un autre appel de bibliothèque bloquant" - la norme est assez claire et ne répertorie que les opérations d'E / S. Pourquoi ajoutez-vous "ou un autre appel de bibliothèque bloquant"? En outre, cette opération d' E / S est déjà inclus dans votre précédente « certains comportements observables ».
MSalters
1
@MSalters std::mutex::lock()est un appel de bibliothèque qui est une opération de synchronisation, relevant de la quatrième puce. Il n'est donc pas vrai que seuls les appels d'E / S sont mentionnés.
Igor Tandetnik
S'il est bloqué en entrée , mais n'en obtient jamais, il est discutable que cela compte comme observable.
Daniel H
4

Oui. De[intro.progress]

L'implémentation peut supposer que n'importe quel thread finira par effectuer l'une des opérations suivantes:

  • mettre fin,
  • appeler une fonction d'E / S de bibliothèque,
  • effectuer un accès via une valeur gl volatile, ou
  • effectuer une opération de synchronisation ou une opération atomique.

[ Remarque: Ceci est destiné à permettre des transformations du compilateur telles que la suppression de boucles vides, même lorsque la terminaison ne peut pas être prouvée. - note de fin ]

Caleth
la source
Je crois qu'une petite description indiquant que le programme fait des E / S serait souhaitable.
KamilCuk
Donc, tant que les fonctions get_inputet put_outputdans l'exemple OP "font un appel à une fonction d'E / S de bibliothèque", le programme doit être valide même s'il ne se termine pas?
Un programmeur du
@Someprogrammerdude ou accédez à une valeur volatile ou atomique, Oui
Caleth
curieux de connaître la norme pré c ++ 11, alors qu'il n'y avait pas le modèle de mémoire actuel.
bolov
1
compiler does not know- Ce n'est pas pertinent. Le compilateur peut savoir et ne pas savoir, du point de vue de la couche linguistique - la question est de savoir s'il est valide, dans tous les cas.
KamilCuk