MooseBoys
MooseBoys

Reputation: 6793

Testing Undefined Behavior

Is it possible, within the confines of only the C++ language, to write a test that isolates and detects undefined behavior when executed? For example, given the following code:

void fn(int* p) {
  int x = *p;
}

void foo() {
  int x = 42;
  fn(&x);
}

void bar() {
  fn(nullptr);
}

Is it possible to construct a test that invokes foo and bar, and "passes" for foo but "fails" for bar? My assumption is that it is not possible because the very act of invoking bar means the compiler is free to generate code that always passes, always fails, only fails on Tuesdays, or just prints "thanks for all the fish" in an endless loop. Still I'd like to get confirmation from the experts that this is the case.

Note: I'm aware of things like clang's ubsan, static analysis tools, and platform-specific traps to assist with detection of UB, but my question is limited to the C++ language only.

Upvotes: 5

Views: 960

Answers (3)

Bendik Hillestad
Bendik Hillestad

Reputation: 191

If the functions can be written as constexpr, and you're okay with the code not compiling if there is an error, you can catch quite a few cases. The compiler will often be friendly enough to tell you why. For example in your case, GCC says this:

error: dereferencing a null pointer

The trick is that undefined behavior is not allowed in a constant expression. https://gcc.godbolt.org/z/XnIrnX

constexpr void fn(int* p) {
  int x = *p;
}

constexpr void foo() {
  int x = 42;
  fn(&x);
}

constexpr void bar() {
  fn(nullptr);
}

//No error here
static_assert([]() constexpr -> bool { foo(); return true; }());

//This line gets an error
static_assert([]() constexpr -> bool { bar(); return true; }());

Upvotes: 1

Daniel Langr
Daniel Langr

Reputation: 23497

Undefined behavior is defined as a behavior for which the C++ Standard imposes no requirements. This basically means that the defined behavior is imposed by the requirements from the Standard.

You can never tell whether some behavior is defined or undefined just by observing that behavior (in both cases, the observable behavior may be the very same). You may only want to check whether all the requirements from the Standard have been met. However, such check is generally infeasible.


Consider your simple example. You can check p for null pointer, but, if it's not null, there is no way to tell whether it actually does or does not point to a valid object of type int. It might be possible in your simple program, provided it's compiled as a standalone translation unit, but generally it is not.

Upvotes: 6

eerorika
eerorika

Reputation: 238361

Your reasoning is sound and it is indeed not possible to test for undefined behaviour within the confines of the C++ language.

Upvotes: 2

Related Questions