[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