GCC optimization re-order statements

Jonny Grant jg@jguk.org
Fri Jun 11 20:52:12 GMT 2021



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.


More information about the Gcc-help mailing list