1) your test suite works over several revisions of the compiler
2) after you upgrade, suddenly one test fails (especially if it's out of hundreds)
2a) you can isolate the minimum condition and it really leaves your head scratching
3) rewriting the code in a slightly different way makes it pass
The time I found a compiler bug it was because of an optimization that missed a corner case that I just happened to be using.
Broken: table[table_i].values[j] && j<category_map_count && to_i<category_array_len; Fixed: j<category_map_count && table[table_i].values[j] && to_i<category_array_len;
Optimizer: "j was used to access values array, j outside array would be undefined behavior, therefore it must have been within the array boundaries and does not need to be tested."
Oh, and threading bugs where some variable that should have been mutex locked or made atomic gets moved in or out of a register depending on the phase of the moon, causing other threads to fail to notice changes to that variable...but add a debug line and it suddenly works.
int foo(struct data *data) {
struct member *member = &data->member;
if (data == NULL) {
return -EINVAL;
}
// Do stuff
}
Assigning a value to member is just a matter of taking data and adding the value of member, so won't explode if data is NULL since it's not actually dereferencing that address. But this is still in undefined behaviour territory, so gcc assumed that we must know that data could never be NULL and optimised out the check.This sort of thing is why I have definite feelings about the use of C in security sensitive contexts.