Renders the entire program meaningless if certain rules of the language are violated.
The C++ standard precisely defines the observable behavior of every C++ program that does not fall into one of the following classes:
std::size_t or the number of bits in a byte, or the text of std::bad_alloc::what. A subset of implementation-defined behavior is locale-specific behavior, which depends on the implementation-supplied locale. Because correct C++ programs are free of undefined behavior, compilers may produce unexpected results when a program that actually has UB is compiled with optimization enabled:
For example,
int foo(int x) {
return x+1 > x; // either true or UB due to signed overflow
}may be compiled as (demo).
foo(int):
movl $1, %eax
retint table[4] = {};
bool exists_in_table(int v)
{
// return true in one of the first 4 iterations or UB due to out-of-bounds access
for (int i = 0; i <= 4; i++) {
if (table[i] == v) return true;
}
return false;
}May be compiled as (demo).
exists_in_table(int):
movl $1, %eax
retstd::size_t f(int x)
{
std::size_t a;
if(x) // either x nonzero or UB
a = 42;
return a;
}May be compiled as (demo).
f(int):
mov eax, 42
retthe output shown was observed on an older version of gcc.
bool p; // uninitialized local variable
if(p) // UB access to uninitialized scalar
std::puts("p is true");
if(!p) // UB access to uninitialized scalar
std::puts("p is false");Possible output:
p is true p is false
int f() {
bool b = true;
unsigned char* p = reinterpret_cast<unsigned char*>(&b);
*p = 10;
// reading from b is now UB
return b == 0;
}May be compiled as (demo).
f():
movl $11, %eax
retint foo(int* p) {
int x = *p;
if(!p) return x; // Either UB above or this branch is never taken
else return 0;
}
int bar() {
int* p = nullptr;
return *p; // Unconditional UB
}may be compiled as (foo with gcc, bar with clang).
foo(int*):
xorl %eax, %eax
ret
bar():
retqChoose clang to observe the output shown.
#include <iostream>
#include <cstdlib>
int main() {
int *p = (int*)std::malloc(sizeof(int));
int *q = (int*)std::realloc(p, sizeof(int));
*p = 1; // UB access to a pointer that was passed to realloc
*q = 2;
if (p == q) // UB access to a pointer that was passed to realloc
std::cout << *p << *q << '\n';
}Possible output:
12
Choose clang to observe the output shown.
#include <iostream>
int fermat() {
const int MAX = 1000;
int a=1,b=1,c=1;
// Endless loop with no side effects is UB
while (1) {
if (((a*a*a) == ((b*b*b)+(c*c*c)))) return 1;
a++;
if (a>MAX) { a=1; b++; }
if (b>MAX) { b=1; c++; }
if (c>MAX) { c=1;}
}
return 0;
}
int main() {
if (fermat())
std::cout << "Fermat's Last Theorem has been disproved.\n";
else
std::cout << "Fermat's Last Theorem has not been disproved.\n";
}Possible output:
Fermat's Last Theorem has been disproved.
© cppreference.com
Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.
http://en.cppreference.com/w/cpp/language/ub