On 11/06/2021 12:56, David Brown wrote: > On 11/06/2021 11:37, Jonny Grant wrote: >> Hello >> This isn't real code, it's just an example to ask this question: >> >> Would GCC optimizer ever re-order these statements and cause a NULL ptr de-reference SIGSEGV? I recall reading a Chris Lattner paper indicating it could happen. >> >> void f(int * p) >> { >> if(!p) >> { >> return; >> } >> >> printf("%d\n", *p); >> } >> >> I which case, a lot of production code faces issues, must be changed to: >> >> void f(int * p) >> { >> if(p) >> { >> printf("%d\n", *p); >> } >> } > > These two functions have identical semantics. > >> >> Jonny >> > > The optimiser never (baring bugs in the compiler, but those are rare!) > rearranges code in a way that changes side-effects in well-defined code. > If code hits undefined behaviour, the compiler can do anything. > > Thus if you write: > > void f2(int *p) { > int x = *p; > if (p) printf("%d\n", x); > } > > the compiler can reason that either p is null, or it is not null. If it > is not null, the "if (p)" conditional is always true and can be skipped. > If it /is/ null, then dereferencing it to read *p is undefined > behaviour - and the compiler can assume the programmer doesn't care what > happens. > > So the code can be optimised to: > > void f2(int *p) { > printf("%d\n", *p); > } Ok I see, because the dereference was before, it was safe to remove the check after. But with code checking the pointer first, it would still be retained. That is good :) > > If the compiler knows that on the target in question, it is perfectly > safe (i.e., no signals or anything else) to dereference a null pointer, > then in your original "f" the compiler could read *p before it tests p > for null, but it could not do the printf before the test. (Sometimes > for embedded systems the compiler knows that reading via a null pointer > is safe.) Yes, exactly, on SH2A I reading from address 0x0 didn't cause a problem. Difficult to detect that kind of bug. So I used to set a hardware address exception on reads from 0x0 to catch.