[vox-tech] Nifty macro expansion bug
Gabriel G. Rosa
grosa at ucdavis.edu
Thu Jan 18 17:27:20 PST 2007
On Thu, Jan 18, 2007 at 04:14:22PM -0800, Bill Kendrick wrote:
>
> So at work, a coworker noticed an issue with the following code:
>
> for (i = 0; i < n; i++)
> myFREE(foo[i]);
>
> which went away when he wrapped it in braces:
>
> for (i = 0; i < n; i++)
> {
> myFREE(foo[i]);
> }
>
> Figured maybe it was a weird compiler bug. Being author of the myFREE()
> code -- which happens to be a macro -- I realized immediately what I did
> wrong. (And continue to be annoyed with C syntax ;) )
>
> See, myFREE() is actually a macro that looks like this:
>
> #define myFREE(x) if ((x) != NULL) FREE(x); x = NULL;
>
> Two statements... hence the need for {} around the call to the macro.
> (Or, more sensibly, including {}s around what the macro expands to.)
>
> That was a neat catch. :)
>
I believe the standard way of doing macros in the linux kernel is to use a
bogus do-while, ie:
#define CRASHMACHINE() do { laughtAtUser(); crashMachine(); } while(0);
that way, any expansion like:
if(completelyRandomCondition())
CRASHMACHINE();
doesn't end up being expanded as:
if(completelyRandomCondition())
laughAtUser(); crashMachine();
^ oops, outside of if scope
but as
if(completelyRandomCondition())
do ( laughAtUser(); crashMachine(); } while(0);
which will execute once and only once.
I saw a good post on this once, but I can't really remember where.
-Gabe
More information about the vox-tech
mailing list