3

According to Wikipedia and this, this code is undefined behavior:

#include <iostream>
int main(int, char**) {
    int data[1] = {123};
    int* p = data + 5; // undefined behavior
    std::cout << *(p - 5) << std::endl;
}

Compiled with clang++-6.0 -fsanitize=undefined and executed, the undefined behavior is detected which is fantastic, I get this message:

ub.cpp:5:19: runtime error: index 5 out of bounds for type 'int [1]'

But when I don't use an array, the undefined behavior is not detectable:

#include <iostream>
int main(int, char**) {
    int data = 123;
    int* p = &data + 5; // undefined behavior
    std::cout << *(p - 5) << std::endl;
}

The sanitizer detects nothing, even though this is still undefined behavior. Valgrind also does not show any problem. Any way to detect this undefined behavior?

Since I am never accessing any invalid data, this is not a duplicate of Recommended way to track down array out-of-bound access/write in C program.

martinus
  • 17,736
  • 15
  • 72
  • 92
  • Comments are not for extended discussion; this conversation has been [moved to chat](https://chat.stackoverflow.com/rooms/192396/discussion-on-question-by-martinus-out-of-bounds-pointer-arithmetic-not-detected). – Samuel Liew Apr 26 '19 at 00:23

1 Answers1

4

The standard very clearly specifies that most forms of undefined behaviour is "no diagnostic required". Meaning that your compiler is under no obligation to diagnose UB (which would also be unreasonable, since it is very hard to do so in many cases). Instead, the compiler is allowed to just assume that you "of course did not" write any UB and generate code as if you didn't. And if you did, that's on you and you get to keep the broken pieces.

Some tools (like asan and ubsan and turning your compilers warning level to 11) will detect some UB for you. But not all.

Your compiler implementors are not out to harm you. They do try to warn you of UB when they can. So, at the very least you should enable all warnings and let them help you as best they can.

One way to detect UB is to have intimate knowledge of the C++ standard and read code really carefully. But, you cannot really do better than that + let some tools help you find the low-hanging fruit. You just have to know (all) the rules and know what you are doing.

There are no training wheels or similar in C++.

Jesper Juhl
  • 30,449
  • 3
  • 47
  • 70