The following code running compiler options -O3
vs -O0
results different output:
#include <stdlib.h>
#include <stdio.h>
int main(){
int *p = (int*)malloc(sizeof(int));
int *q = (int*)realloc(p, sizeof(int));
*p = 1;
*q = 2;
if (p == q)
printf("%d %d", *p, *q);
return 0;
}
I was very surprised with the outcome.
using compiler options -O0
— output: 2 2
using compiler options -O3
— output: 1 2
Is it a bug?
Interestingly if I modify the code slightly it behaves as expected.
int *p = (int*)malloc(sizeof(int));
*p = 1;
Testing it on gcc seems to work fine.
Assuming both of the allocations are successful, q
points to an allocated region of memory and p
is an invalid pointer. The standard treats realloc
and free
as deallocation routines, and if successful, the address the pointer held can no longer be used. If the call to realloc
fails for some reason, the original memory is still valid (but of course q
isn't, it's NULL).
Although you compare p
and q
, you've already written to an invalid pointer, so all bets are off.
What's probably happening here is that the O3
setting is causing the compiler to ignore the pointers and just substitute numbers inline. High optimisation means a compiler can take all sorts of short cuts and ignore statements so long as it guarantees the same result - the condition being that all of the code is well defined.