Kevin Song
I'm a student at UT (that's the one in Austin) who studies things.
A K. Song Production
int dumb()
{
int a,b,c;
a = 5;
b = 7;
c = a + b;
return c;
}dumb:
addiu $s0, $0, 5 #a = 5
addiu $s1, $1, 7 #b = 7
addu $t0, $s0, $s1 #c = a + b
addiu $v0, $t0, 0 #mv to ret
jr $ra #returndumb:
addiu $v0, $0, 12
jr $ra #return 12More "accurate"
Doesn't suck
int x = 10;
x = x++ * ++x;int main(){
//Integer overflow is undefined!
int y = (INT_MAX + 1) > 0;
printf("%d\n", y);
return 0;
}chip@diglett$ ./overflow
42
chip@diglett$ chip@diglett$ ./overflow
1
chip@diglett$ chip@diglett$ ./overflow
0
chip@diglett$ chip@diglett$ ./overflow
Issuing "rm -rf /", please wait
while we format your hard drive.
This process cannot be interrupted.
^C^C^C^C^C^C^C^C^C^C^C^CExamples from http://blog.regehr.org/archives/213
int unsafe_div (int a, int b) {
return a / b;
}Case b != 0:
-Emit code to divide a by b
Case b == 0:
-Compiler has no obligations
-Does not need to generate trap code
float* P = malloc(sizeof(float) * 10000);
int* I = malloc(sizeof(int) * 10000);
void zero_array() {
int i;
for (i = 0; i < 10000; ++i)
I[i] = i;
P[i] = 0.0f;
}Case I and P do not alias:
-Can optimize P to memset()
Case I and P alias:
-Compiler has no obligations
-Optimization: ignore this case!
int dumb (int a) {
return a < (a+1);
}Case a != INT_MAX:
-a is obviously less than a+1
-Simply return 1
Case a == INT_MAX:
-Compiler has no obligations
-Optimization: ignore this case! (branching is slow)
typedef struct Data{
int* thingy;
//More declarations here
} Data;
void smart_thing(Data* input){
int* thing = input->thingy;
if (input == NULL) return;
//Do more stuff with input
}Case input == NULL:
-input -> thingy is undefined
-Compiler has no obligations
Case input != NULL:
-Null check is redundant
-Optimization: kill null check (branching is slow)
We don't want the compiler to warn us about everything!
Examples:
People don't want warnings from inside of dead code---but the compiler can't prove it's dead!
int i, z, *x;
for(i = 0; i < a.size(); i++){
if (a[i] < 0){ //DEAD CODE
a[i]--;
(*(x) <<= z);
}
//Do stuff
}Taken from http://blog.llvm.org/2011/05/what-every-c-programmer-should-know_21.html
warning: after 3 levels of inlining (potentially across files with Link Time Optimization), some common subexpression elimination, after hoisting this thing out of a loop and proving that these 13 pointers don't alias, we found a case where you're doing something undefined. This could either be because there is a bug in your code, or because you have macros and inlining and the invalid code is dynamically unreachable but we can't prove that it is dead.
Use tools to help you analyze these things:
Questions? Comments?
C compilers use undefined behavior to optimize the code they produce
Undefined behavior can do anything it wants
Undefined behavior can pop up at when least expected and change the program's behavior.
The best defense against undefined behavior is to judiciously use all bug-checking tools available.
Do not rely on undefined behavior! Null pointer dereferences might not segfault, integer overflow may not trap!
By Kevin Song
This can really ruin your day if you're not careful about it
I'm a student at UT (that's the one in Austin) who studies things.