Interesting issue we came across here this week.
We are working in C on a Harvard Architecture embedded platform, which has 16-bit data addresses and 32-bit code addresses.
The issue occurs when you are working with function pointers. If you have code like
if (fp) fp();
or
if (fp != 0) fp();
everything is fine.
However if you have code like
if (fp != NULL) fp();
then, because NULL
is defined as (void *) 0
, the compiler (gcc in this case) a) does not warn and b) does a 16-bit comparison against your function pointer instead of a 32-bit comparison. Fine as long as your function pointer doesn't happen to lie on a 64k boundary so all bottom 16 bits are 0.
At the moment we have large swathes of code which contain explicit checks against NULL. Most of them will be data pointers, but some of them will be function pointers. A quick grep for != NULL
or == NULL
revealed over 3000 results, to many to go through manually to check.
So, what we would like now would be either
a way to find all the cases where function pointers (but not data pointers) are compared (so we can instead have them compare against FP_NULL which we would define as a 32-bit 0), or
to redefine NULL in such a way that it would do the right thing.
(Or, I suppose, to update our gcc port to detect and correctly handle this case).
I can't think of any approach that works for 1. The only approach I can think of for 2 is to redefine NULL as a 0 function pointer, which would be very wasteful for the vast majority of comparisons which are against data pointers. (A 32-bit compare is 4 instructions, a 16-bit compare is 1 instruction).
Any thoughts or suggestions?