Reputation: 508
Here is a toy example that I thought would invoke undefined behaviour:
#include <cstdint>
#include <iostream>
#include <vector>
int
main()
{
std::vector<uint16_t> foo = {0, 0x42F6};
std::cout << *reinterpret_cast<float*>(foo.data()) << std::endl;
return 0;
}
I was pretty certain that dereferencing the result of that reinterpret_cast
would violate the strict aliasing rules. However:
$ g++ --version
g++ (Ubuntu 5.4.0-6ubuntu1~16.04.10) 5.4.0 20160609
$ g++ -fstrict-aliasing -Wstrict-aliasing -fsanitize=undefined -std=c++14 -o a a.cpp
$ ./a
123
No warnings from the compiler or the UB sanitizer. Why not?
Upvotes: 2
Views: 471
Reputation: 81189
The fact that the Standard does not require implementations to define the behavior of some construct does not imply that implementations intended to be suitable for various purposes shouldn't define it anyway. Many implementations have various options that will cause the compiler to consistently treat some such constructs as defined in ways that are sometimes useful or even necessary to programmers writing certain kinds of code (even though the Standard does not require it).
With regard to your example, there are some implementations where invocation with a suitable combination of options would yield behavior defined precisely as what you see. On many implementations, the required options would include -fno-strict-aliasing
, though some may require other options as well. Some implementations, however, especially those where a vector<uin16_t>
might not be 32-bit aligned, and where loading a float
will fail if it isn't 32-bit aligned, may not support any combination of options that would define the behavior.
Slightly confusing the matter, however, is the fact that even when such options are not used (or not supported), many implementations will treat those constructs in the a fashion that will often--though not reliably--coincide with the way they would if such options were specified and supported. This can make it difficult to determine whether a piece of code can be expected to work consistently, or may sometimes work and sometimes fail, in unpredictable fashion.
Upvotes: 0
Reputation: 238361
Why is this type punning not undefined behavior?
Your premise is wrong. The behaviour is undefined.
No warnings from the compiler ... Why not?
A compiler is not required to warn about UB. Sometimes it does, when the stars align, but it is in general prohibitively expensive for the compiler to prove the existence of UB. In fact, if it was possible, then the language rules probably would have specified the program to be ill-formed instead.
or the UB sanitizer. Why not?
The UB sanitizer isn't perfect. It cannot detect all UB. Consider filing a feature request for implementing detection of this case - assuming it hasn't already been requested.
Upvotes: 6
Reputation: 93304
No warnings from the compiler or the UB sanitizer. Why not?
This doesn't mean you do not have undefined behavior. The compiler and sanitizer can do their best to detect it, but it's not guaranteed to catch every occurrence of it.
The only way you can be sure is by reading the Standard and checking whether your usage of reinterpret_cast
is well-defined.
Upvotes: 5