#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
из функции. Компилятор просто не может сделать это правильно, и это не вина компиляторов.