पाठ 21 / 25

Undefined Behaviour, Sanitizers and Common Bugs

Recognise undefined behaviour and catch bugs with warnings, sanitizers and tools.

When the standard makes no promises

Undefined behaviour (UB) means the C++ standard places no requirements on what happens: the program may crash, appear to work, or behave differently with another compiler or optimisation level, because optimisers assume UB never happens. Common sources: out-of-bounds array or vector access with [], dereferencing null or dangling pointers, use after free, signed integer overflow, uninitialised variables, data races, double delete, invalid iterator use after container modification, and returning references to locals. Defences: compile with warnings (-Wall -Wextra) and treat them as errors; use sanitizers in test builds, namely AddressSanitizer (-fsanitize=address) for memory errors, UndefinedBehaviorSanitizer (-fsanitize=undefined) for overflow and similar issues, and ThreadSanitizer (-fsanitize=thread) for data races; run static analysers such as clang-tidy; use .at() instead of [] where bounds are uncertain; and follow the C++ Core Guidelines. Many of these bugs disappear entirely when you use RAII, containers and references instead of raw pointers and manual memory.

Bugs that sanitizers catch

Each line compiles; each is undefined behaviour.

#include <climits>
#include <vector>

int main() {
    std::vector<int> v{1, 2, 3};
    int a = v[3];                 // out of bounds: UB (v.at(3) would throw instead)

    int* p = new int{5};
    delete p;
    int b = *p;                   // use after free: UB

    int big = INT_MAX;
    big = big + 1;                // signed overflow: UB

    int uninit;
    int c = uninit * 2;           // reading an uninitialised variable: UB
}

// build a test binary with sanitizers:
// g++ -std=c++20 -g -O1 -fsanitize=address,undefined -fno-omit-frame-pointer bugs.cpp -o bugs
// clang++ -std=c++20 -g -fsanitize=thread race.cpp -o race

"It works on my machine" proves nothing

UB can stay hidden for years and appear only with a new compiler version or optimisation flag. Run tests regularly under AddressSanitizer and UndefinedBehaviorSanitizer in CI.

त्वरित जाँच: Which tool detects out-of-bounds accesses and use-after-free at run time?

  • ThreadSanitizer
  • clang-format
  • AddressSanitizer
  • The linker
Answer

AddressSanitizer — AddressSanitizer instruments memory accesses to catch these errors.