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