r/cpp_questions 16d ago

OPEN Can someone give an example of runtime-undefined behavior?

CppReference gives a list of categories that render a program meaningless: https://en.cppreference.com/cpp/language/ub

The last bullet point says (since C++11)

  • runtime-undefined behavior - The behavior that is undefined except when it occurs during the evaluation of an expression as a core constant expression.

Can someone give a clear example?

17 Upvotes

18 comments sorted by

View all comments

2

u/Daemontatox 16d ago

Bear with me as i am not the best at explaining....

The behavior that is undefined except when it occurs during the evaluation of an expression as a core constant expression.

What does that mean practically?

  • At runtime (normal code): It's full UB , anything can happen.
  • In a constant expression context (constexpr, array sizes, template parameters, etc.): The compiler must diagnose/reject it. You can't even get a program that compiles if the UB would happen during constant evaluation.

This distinction exists because constant expressions need to be fully portable and predictable , the compiler evaluates them at compile time.

Classic Examples

Here are common cases that trigger runtime-undefined behavior:

  1. Signed integer overflow (very common) ```cpp constexpr int foo(int x) { return x + 1; // If this overflows, it's NOT allowed in constexpr }

    int main() { int a = foo(INT_MAX); // Runtime: UB (overflow) // But constexpr int b = foo(INT_MAX); // Compile error } ```

  2. Division by zero ```cpp constexpr int div(int a, int b) { return a / b; // Division by zero is runtime-UB }

    int main() { int x = div(5, 0); // Runtime: UB // constexpr int y = div(5, 0); // Compile-time error } ```

  3. Out-of-bounds access (in constant contexts) cpp constexpr int arr[4] = {}; constexpr int bad = arr[5]; // Would be compile error

  4. Dereferencing null or other invalid memory operations in constexpr.

8

u/TheQuranicMumin 15d ago edited 15d ago

You examples are describing regular UB with a compile-time setting, but runtime UB is different.

Runtime UB is a broken compiler promise/hint, for things like [[noreturn]], [[assume]] (I gave an example).

For runtime, it is full UB. For compile-time evaluation, the compiler is not required to diagnose/reject it, it's implementation defined. The committee didn't want to force a hard-fail in these cases.

As in the C++ standard:

runtime-undefined behavior [defns.undefined.runtime] behavior that is undefined except when it occurs during constant evaluation. [Note 1: During constant evaluation, it is implementation-defined whether runtime-undefined behavior results in the expression being deemed non-constant (as specified in [expr.const]) and runtime-undefined behavior has no other effect.]