Who Am I?
Don’t care
Already know
Who Am I?
Don’t care
Already know
Who Are You?
Want to learn about
undefined behavior
Already know
Square
example
Confusing terminology
Not defined
Unspecified behavior
Implementation defined behavior
Undefined Behavior
behavior, upon use of a nonportable or erroneous program construct or of erroneous data, for which this International Standard imposes no requirements
C++ standard, defns.undefined
The compiler is free to assume
Undefined Behavior never
happens
Chekhov's Gun
(not my example, not example’s original name)
What are UBs good for?
“NULL pointer dereference crashes the program”
void crash_preventer(int signum) {
exit(1);
}
int main() {
signal(SIGSEGV, crash_preventer);
…
“NULL ptr deref raises a segmentation fault”
int main() {
void *ptr = mmap(� NULL,� 4096,� PROT_READ|PROT_WRITE,� MAP_ANONYMOUS|MAP_FIXED,� -1,� 0);
…
UBs are a necessary evil
UB’s “bad” behavior is a result of optimization
Not a rule, just an observation
Optimization steps
define i32 @some_func() {
create_frame
%1 = alloca i32, align 4
%2 = 42
store i32 %2, ptr %1
%3 = load i32, ptr %1
ret i32 %3
}
Optimization steps
define i32 @some_func() {
create_frame
%1 = alloca i32, align 4
%2 = 42
store i32 %2, ptr %1
ret i32 %2
}
Optimization steps
define i32 @some_func() {
create_frame
%1 = alloca i32, align 4
%2 = 42
ret i32 %2
}
Optimization steps
define i32 @some_func() {
create_frame
%1 = 42
ret i32 %1
}
Optimization steps
define i32 @some_func() {
%1 = 42
ret i32 %1
}
Peephole Optimization
A series of small code replacement, each retaining semantic meaning.
Breakdown of Chekhov's gun example
Null pointer dereference
doesn’t always look like
Null pointer dereference
Real Life Examples
Presented in a useless form
Example 1 - PLL initialization
Example 2 - hardware register
Signed Int Overflow
int func1(int);
int func2(int);
int func(int param) {
int sum = 0;
while(sum<5000) {
if( param<10 )
sum+=func1(param);
else
sum+=func2(param);
param++;
}
return sum;
}
Null Pointer Deref - Chekhov's gun example
secondfile.cpp:
#include <iostream>
extern void load_gun();
class Loader {
public:
Loader() {
std::cout<<"Loading gun\n";
load_gun();
}
};
static Loader loader;
UB scope expansion example
#define OFFSETOF(T,m)
static_cast<size_t>(
&reinterpret_cast<T*>(nullptr)->m
)
Using keywords restricts versatility
template<
typename T,
ListNode T::*offset>�class IntrusiveLinkedList {
At least we know which UBs there are… ??
We can search the standard for “Undefined behavior”
Kinda
Searching for just “undefined” has false positives…
“Behavior is undefined” will find most
Even the standard sometimes can’t tell them apart
Some don’t have the word “undefined” at all
How can things be made better?
UBs are a necessary evil
Slide #2 - Who am I?
Thank you