Неопределённое поведение в недостижимом коде

Содержит ли следующий код UB или надо вызвать функцию для этого?

int foo() {
   int a = 2 + 3;
   // no return
}

int main() {
   // foo();
}

Ответы (3 шт):

Автор решения: 0x25

Нашёл ответ на похожий вопрос. Спасибо LShadow77 за помощь.

https://stackoverflow.com/a/23154502

So, an unreachable statement with UB doesn't give the program UB.

→ Ссылка
Автор решения: HolyBlackCat

Нет здесь никакого неопределенного поведения.

У UB бывает два вида причин:

  1. Времени компиляции. (Например, использование зарезервированного идетификатора.)

  2. Времени выполнения. (Например целочисленное деление на ноль.)

Во втором случае, чтобы поведение стало неопределенным, выполнение должно достичь1 какого-то участка кода, про который в стандарте написано, что он вызывает неопределенное поведение (или его поведение не описано вообще). (см 1 2 3)

У нас второй случай:

[stmt.return]/2

Flowing off the end of a ... function with a cv void return type is equivalent to a return with no operand. Otherwise flowing off the end of a function ... results in undefined behavior.

(выделение добавлено мной)

Написано, "если выполнение выходит из функции...", т.е. во время выполнения. Если бы речь шла о времени компиляции, то так и написали бы: "если любой возможный путь выполнения функции всегда достигает ее конца...".


1 Точнее, UB появляется когда выполнение вызывающего его кода становится неизбежным. Пример: программа может проигнорировать условие if-а и отказаться заходить в ветку, которая всегда вызывает UB.

→ Ссылка
Автор решения: user7860670

Я склоняюсь к тому, что неопределенное поведение тут есть. Дело в том, что стандарт позволяет реализации содержать ряд допущений относительно потока исполнения:

6.9.2.2 Forward progress [intro.progress]
1 The implementation may assume that any thread will eventually do one of the following:
— (1.1) terminate,
— (1.2) make a call to a library I/O function,
— (1.3) perform an access through a volatile glvalue, or
— (1.4) perform a synchronization operation or an atomic operation.

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

→ Ссылка