Um programa que nunca termina um programa C ++ válido?

15

É necessário um programa para terminar? Em outras palavras, é um programa que roda para sempre tecnicamente Comportamento indefinido? Observe que não se trata de loops vazios. Falando sobre programas que fazem "coisas" (ou seja, comportamento observável) para sempre.

Por exemplo, algo como isto:

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

Esta é mais uma questão acadêmica, pois empiricamente todos os compiladores sãos geram o código esperado para o tipo de programa acima (assumindo, é claro, nenhuma outra fonte de UB). E sim, é claro que existem muitos programas que nunca terminam (SO, incorporado, servidores). No entanto, o padrão é peculiar às vezes, daí a questão.


Tangencial: muitas (algumas?) Definições de "algoritmo" requerem que um algoritmo seja finalizado , ou seja, uma série de operações que nunca termina não é considerada um algoritmo.


Tangencial. O problema de parada afirma que não existe um algoritmo para determinar se um programa arbitrário termina para uma entrada. No entanto, para esse programa em particular, uma vez que não há ramificação que saia do main, o compilador pode determinar facilmente que o programa nunca terminará. No entanto, isso é irrelevante, pois a questão é o advogado da linguagem.

Bolov
fonte
Comentários não são para discussão prolongada; esta conversa foi movida para o bate-papo .
Samuel Liew

Respostas:

15

Não há nada no padrão C ++ que exija que o programa, ou qualquer thread fornecido, seja finalizado. A coisa mais próxima disso é [intro.progress] p1 , que diz

A implementação pode assumir que qualquer thread acabará por executar um dos seguintes procedimentos:

  • terminar,
  • faça uma chamada para uma função de E / S da biblioteca,
  • realizar um acesso através de um valor de volume volátil ou
  • executar uma operação de sincronização ou uma operação atômica.

[  Nota: O objetivo é permitir transformações do compilador, como remoção de loops vazios, mesmo quando a finalização não puder ser comprovada. -  nota final  ]

Contanto que exista algum comportamento observável, eventualmente, ou contanto que gaste todo o seu tempo bloqueado em uma operação de E / S ou outra chamada de biblioteca de bloqueio, isso não se aplica e o programa é válido (supondo que atenda a todas as outros critérios de validade).

Daniel H
fonte
"uma operação de E / S ou outra chamada de biblioteca de bloqueio" - o Standard é bastante claro e lista apenas as operações de E / S. Por que você está adicionando "ou outra chamada de bloqueio da biblioteca"? Além disso, que operação E / S está já incluído no seu "anteriormente algum comportamento observável".
MSalters
11
@MSalters std::mutex::lock()é uma chamada de biblioteca que é uma operação de sincronização, abrangendo o quarto marcador. Portanto, não é verdade que apenas as chamadas de E / S sejam mencionadas.
Igor Tandetnik 5/11/19
Se está preso na entrada , mas nunca recebe, é discutível se isso conta como observável.
Daniel H
4

Sim. De[intro.progress]

A implementação pode assumir que qualquer thread acabará por executar um dos seguintes procedimentos:

  • terminar,
  • faça uma chamada para uma função de E / S da biblioteca,
  • realizar um acesso através de um valor de volume volátil ou
  • executar uma operação de sincronização ou uma operação atômica.

[ Nota: O objetivo é permitir transformações do compilador, como remoção de loops vazios, mesmo quando a finalização não puder ser comprovada. - nota final ]

Caleth
fonte
Acredito que uma pequena descrição afirmando que o programa faz E / S seria aconselhável.
27519 K KamilCuk
Portanto, desde que as funções get_inpute put_outputno exemplo dos OPs "façam uma chamada para uma função de E / S da biblioteca", o programa deve ser válido mesmo que não seja finalizado?
Algum programador
@Someprogrammerdude ou acesso um valor volátil ou atômica, Sim
Caleth
curioso sobre o padrão pré c ++ 11, quando não havia o modelo de memória atual.
Bolov #
11
compiler does not knowIsso é irrelevante. O compilador pode saber e pode não saber, do ponto de vista da camada de idioma - a questão é se é válida, em qualquer caso.
KamilCuk #