I have the following C++ code:
void bar(int&);
void baz();
void foo(std::vector<int>& v) {
int* pointer_to_last = v.data() + (v.size() - 1);
if (v.size() > 0 && *pointer_to_last == 42) {
bar(*pointer_to_last);
} else {
baz();
}
}
I'm unconditionally creating a pointer to the last element of a vector, but I'm only dereferencing the pointer if the vector is not empty. Is this legal according to the standard or does the code above contain undefined behaviour?
If the above program is legal, is the following program legal as well?
void bar(int&);
void baz();
void foo(std::vector<int>& v) {
int& reference_to_last = v.back();
if (v.size() > 0 && reference_to_last == 42) {
bar(reference_to_last);
} else {
baz();
}
}
The reference for std::vector::back says
Calling back on an empty container causes undefined behavior.
So I'm assuming this program is not legal. Are there any compiler flags for GCC or Clang or any static analyzers that give me a warning for the code above?
Both are illegal. The former is rejected by UBSAN (aka
-fsanitize=undefined) (see[expr.add]/4)And the latter is rejected by
-D_GLIBCXX_DEBUG:The two above, plus
-fsanitize=address.-D_GLIBCXX_DEBUGis libstdc++-specific. If you use Clang with libc++ instead of libstdc++, then use-D_LIBCPP_ENABLE_DEBUG_MODE. (It seems to require libc++ 17 or newer, their debug mode was broken for a while. It also seems to lack iterator validation. :c)