[vox-tech] Nifty macro expansion bug
Gabriel G. Rosa
grosa at ucdavis.edu
Thu Jan 18 17:31:34 PST 2007
On Thu, Jan 18, 2007 at 05:27:20PM -0800, Gabriel G. Rosa wrote:
> 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.
>
Oh, and right after I hit send the real reason for the do-while instead
of just {} comes to me, as does where I read it:
http://kernelnewbies.org/FAQ/DoWhile0
-Gabe
More information about the vox-tech
mailing list