C : цикл for оптимизирован в бесконечный цикл, если отсутствует оператор возврата функции — ошибка компилятора?

#c #compiler-optimization #internal-compiler-error

Вопрос:

Возьмем следующий минимальный пример:

 #include <stdio.h>

bool test(){
    for (int i = 0; i < 1024; i  )
    {
        printf("i=%dn", i);
    }
}
int main(){
    test();
    return 0;
}
 

где оператор return в test функции отсутствует. Если я приведу пример так:

 g    main.cpp -o main amp;amp; ./main
 

Затем цикл прерывается после 1024 итераций. Однако, если я запущу пример с включенной оптимизацией:

 g    -O3 main.cpp -o main amp;amp; ./main
 

Затем это оптимизируется, и я получаю бесконечный цикл.

Такое поведение согласуется между g версиями 10.3.1 и clang версиями 10.0.1 . Бесконечный цикл не возникает, если я добавляю оператор return или изменяю тип возвращаемой функции на void .

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

Комментарии:

1. отсутствует return неопределенное поведение. Компилятор не уполномочен извлекать что-либо значимое из вашего кода.

2. Это то, что можно было бы считать ошибкой компилятора? Нет.

3. Компилятор может предположить, что функция никогда не достигнет конца, потому что это было бы неопределенным поведением. Таким образом, можно предположить, что цикл никогда не заканчивается. Это не ошибка компилятора, это ошибка в вашем коде.

4. Это интересный пример последствий UB, потому что он просто и ясно показывает, что UB может влиять на поведение без контроля при каждом фактическом достижении точки, содержащей UB.

Ответ №1:

Ваша функция объявлена как bool test() , но ваше определение никогда ничего не возвращает. Это означает, что вы разорвали контракт с языком и вынуждены взять тайм-аут в стране неопределенного поведения. Там все результаты «правильные».

Комментарии:

1. Обязательное упоминание о носовых демонах .

Ответ №2:

Вы можете думать о неопределенном поведении следующим образом: не определено, какие выходные данные выдает компилятор, когда его просят скомпилировать ваш код.

На самом деле «неопределенный» относится к наблюдаемому поведению программы, которую компилятор создает из вашего кода, но это сводится к тому же.

Это не ошибка компилятора.

Вы попросили компилятор вернуть a bool из функции, не возвращая a bool из функции. Компилятор просто не может сделать это правильно, и это не вина компиляторов.