2016-12-25 5 views
10

Говорят, что бесконечный цикл for(;;); - это неопределенное поведение.Бесконечный цикл все еще неопределенного поведения в C++, если он вызывает общую библиотеку?


От http://en.cppreference.com/w/cpp/language/memory_model

В действующей программе C++, каждый поток в конечном итоге делает один из следующее:

  • прекратить
  • делает вызов в библиотеку ввода/вывода функция
  • считывает или изменяет изменчивый объект
  • выполняет атомную операцию или операцию синхронизации

Нет поток исполнения не может выполнять навсегда без выполнения какого-либо из этих наблюдаемых форм поведение.

Обратите внимание, что это означает, что программа с бесконечной рекурсией или бесконечным циклом (независимо от того, реализована ли она как for-statement или looping goto или в противном случае) имеет неопределенное поведение.


Но что, если она вызывает функцию в общей библиотеке?

for(;;) sofunc();

Функция может сделать любой вид блокировки ввода-вывода, или исключение/бросок.

В этом случае компилятор предполагает, что цикл имеет некоторые наблюдаемые поведения?

+2

Если 'sofunc' не выполняет одну из указанных операций, у вас есть недействительная программа. – Jarod42

+1

Я не знаю каких-либо компиляторов, ОС или ЦП, которые вызывают какие-либо проблемы, используя либо пустой цикл, либо завершающий цикл, который вызывает функцию. вне стандартного мира этот вопрос смешон. У меня нет претензий к OP, я просто думаю, что это не настоящая проблема. –

+0

Но не вызывает ли атомную инструкцию? – Logman

ответ

3

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

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

Стандарт, однако, выходит за рамки этого. Учитывая код:

int foo(void) 
{ 
    int x=0; 
    do 
    { 
    x=functionWithNoSideEffects(x); 
    } while(x != 23 && x != 42); 
    return x; 
} 

компилятор, который может показать, что functionWithNoSideEffects никогда не будет иметь каких-либо определенные побочные эффекты, и никогда не вернется 23 может заменить код «Foo» с «вернуть 42;». Даже если цель программы заключалась в том, чтобы проверить, вернет ли функция WHIDNoSideEffects 42 (в этом случае сгенерированный код возврата 42, будет ли функция делать или нет, будет бесполезным), Стандарт не потребует от компиляторов генерировать код для фактического тестирования, если только цикл включал какой-то «побочный эффект».

Я лично не уверен, что значение того правила, которое говорит, что если компиляторы могут показать, что цикл не может завершиться без X истинно, то они можно рассматривать X как верно ли или нет там какой-либо означает, что это может быть . Однако оптимизация, основанная на этом принципе, кажется популярной.

+2

Почему '23'? Разве это не должно быть ['42'] (https://en.wikipedia.org/wiki/Life__the_Universe_and_Everything)? – wallyk

+0

@wallyk: Я подправил пример, чтобы сделать его немного интереснее. Вам это нравится? – supercat

+0

Определенно улучшение. Но я думал, что есть только один ответ. – wallyk