Consider this simple program:
#include <array>
#include <iostream>
#include <cstdlib>
int main(int argc, char* argv[]) {
std::array<int, 5> arr = {0, 1, 2, 3, 4};
int idx = std::atoi(argv[1]);
int val = std::atoi(argv[2]);
arr[idx] = val;
for (auto i=0u; i <= idx; i++) {
std::cout << "arr[" << i << "] = " << arr[i] << std::endl;
}
}
If I compile and link it with GCC 6.3.1 like this:
g++ -O0 -std=gnu++14 -fsanitize=undefined example.cpp
and run it like this:
a.out 5 98
I don't get any warnings, even though I am writing and reading one element past the end of 'arr' (the array ends at index 4).
If I run:
a.out 6 98
I receive a warning that 'index 6 out of bounds for type 'int [5]'. In this case I am writing and reading two elements past the end of 'arr'.
Why doesn't the off-by-one case throw an error? I guess because one element past the end of an array is a valid memory address (i.e. iterators can point to it?). Can you suggest any other tool that can reliably detect out of bounds access by one element?
EDIT
I can also run:
g++ -O0 -std=gnu++14 -fsanitize=bounds-strict example.cpp
And I see the same behaviour, i.e. out of bounds access by one element does not trigger a warning, but, out of bounds by two elements does. This is the part I'm trying to understand.