Является ли программа, которая никогда не завершает действительную программу C ++?

15

Требуется ли прекращение работы программы? Другими словами, это программа, которая всегда работает технически с неопределенным поведением? Обратите внимание, что это не о пустых циклах. Разговор о программах, которые делают "вещи" (то есть наблюдаемое поведение) навсегда.

Например, что-то вроде этого:

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

Это скорее академический вопрос, поскольку эмпирически все здравомыслящие компиляторы будут генерировать ожидаемый код для вышеуказанного типа программ (при условии, конечно, что нет другого источника UB). И да, конечно, есть много программ, которые никогда не завершаются (os, embeded, серверы). Однако стандарт иногда бывает странным, поэтому возникает вопрос.


Тангенциальный: многие (некоторые?) Определения «алгоритма» требуют, чтобы алгоритм завершился , то есть серия операций, которая никогда не завершается, не считается алгоритмом.


Тангенциальное. Проблема остановки говорит о том, что не может существовать алгоритм, чтобы определить, завершается ли произвольная программа для ввода. Однако для этой конкретной программы, поскольку нет ветки, которая приводит к выходу из main, компилятор может легко определить, что программа никогда не закончится. Это, однако, не имеет значения, поскольку речь идет о языке юриста.

Болов
источник
Комментарии не для расширенного обсуждения; этот разговор был перенесен в чат .
Самуэль Лью

Ответы:

15

В стандарте C ++ нет ничего, что требовало бы завершения программы или любого другого потока. Наиболее близким к этому является [intro.progress] p1 , который говорит

Реализация может предполагать, что любой поток в конечном итоге выполнит одно из следующих действий:

  • прекратить,
  • сделать вызов функции ввода-вывода библиотеки,
  • выполнить доступ через изменчивое glvalue, или
  • выполнить операцию синхронизации или атомарную операцию.

[  Примечание: это предназначено для разрешения преобразований компилятора, таких как удаление пустых циклов, даже если завершение не может быть доказано. -  конец примечания  ]

Пока существует некоторое наблюдаемое поведение, в конце концов, или пока оно тратит все свое время, заблокированное на операцию ввода-вывода или другой блокирующий вызов библиотеки, это не применяется, и программа действительна (при условии, что она соответствует всем другие критерии действительности).

Даниэль Н
источник
«операция ввода-вывода или другой блокирующий вызов библиотеки» - стандарт довольно ясен и содержит только операции ввода-вывода. Почему вы добавляете "или другой блокирующий вызов библиотеки"? Кроме того, эта операция ввода / вывода уже включена в ваше ранее « некоторое наблюдаемое поведение».
MSalters
1
@MSalters std::mutex::lock()- это библиотечный вызов, который представляет собой операцию синхронизации, подпадающую под четвертый пункт. Так что это неправда, что упоминаются только вызовы ввода / вывода.
Игорь Тандетник
Если он застрял на входе , но никогда не получает какой - либо, это спорно ли это считается как наблюдаемые.
Даниэль Х
4

Да. От[intro.progress]

Реализация может предполагать, что любой поток в конечном итоге выполнит одно из следующих действий:

  • прекратить,
  • сделать вызов функции ввода-вывода библиотеки,
  • выполнить доступ через изменчивое glvalue, или
  • выполнить операцию синхронизации или атомарную операцию.

[ Примечание: это предназначено для разрешения преобразований компилятора, таких как удаление пустых циклов, даже если завершение не может быть доказано. - конец примечания ]

Caleth
источник
Я считаю, что было бы целесообразно небольшое описание, утверждающее, что программа выполняет ввод-вывод.
KamilCuk
Так до тех пор , как get_inputи put_outputфункция в примере OPS «сделать вызов библиотечной функции I / O» программа должна быть действительной , даже если она не прекращается?
Какой-то программист чувак
@Someprogrammerdude или получить доступ к энергозависимым или атомным значениям, да
Caleth
Любопытно о стандарте до c ++ 11, когда не было текущей модели памяти.
Болов
1
compiler does not know- Это не имеет значения. Компилятор может знать, а может и не знать, с точки зрения языкового уровня - вопрос в том, является ли он действительным в любом случае.
KamilCuk