[PATCH] Do not warn with warn_unused_result for alloca(0).

Jeff Law law@redhat.com
Thu Jun 13 15:32:00 GMT 2019


On 6/12/19 9:25 AM, Michael Matz wrote:
> Hi,
> 
> On Wed, 12 Jun 2019, Martin Sebor wrote:
> 
>>> Otherwise LGTM as the patch, but I'd like to hear from others whether 
>>> it is kosher to add such a special case to the warn_unused_result 
>>> attribute warning.  And if the agreement is yes, I think it should be 
>>> documented somewhere that alloca (0) will not warn even when the call 
>>> has such an attribute (probably in the description of 
>>> warn_unused_result attribute).
>>
>> I'm not very happy about adding another special case to alloca
>> (on top of not diagnosing zero allocation by -Walloc-zero).
>> There is no valid use case for the zero argument, whether or not
>> the return value is used.
> 
> That's the thing, there _is_ a valid use case for supplying a zero 
> argument and then the returned value should _not_ be used.  There are 
> alloca implementations that do something (freeing memory) when 
> called with a zero size, so some (older) programs contain such calls.  
> Warning on those calls for the unused results is exactly the wrong thing 
> to do, if anything if the result is used we'd have to warn.  (That's of 
> course non-standard, but so is alloca itself)  And just removing these 
> calls isn't correct either except if it's ensured to not use an alloca 
> implementation with that behaviour.
Agreed.  Removing those calls simply can't be right unless you're
dropping support for the old C-alloca implementations completely.

> 
> (In fact I think our builtin_alloca implementation could benefit when we 
> added that behaviour as well; it's a natural wish to be able to free 
> memory that you allocated).
But do we really want to cater to alloca more than we already are?  I'd
argue that programmers simply aren't capable of using alloca
appropriately :-)  That's based on seeing mis-uses exploited repeatedly
through the years.

Also note that simply sprinkling alloca(0) calls won't magically release
memory.  In a stack implementation releasing happens when the frame is
removed.  Doing something more complex than that seems unwise.

In a C implementation, allocations (or groups of allocations) carry
additional information -- specifically the stack pointer at the time the
object was allocated.   Deallocation of the areas only occurs at
subsequent calls to alloca when the current stack pointer is larger than
the saved stack pointer (or if you're on a PA, the opposite :-)

So something like this

for (...)  {
    alloca (space);
}
alloca (0);

Won't release anything because the saved stack pointer for the
allocations in the loop is the same as the stack pointer at the point of
the alloca(0) call.

Where alloca(0) is useful is in something like this:

for (...) {
   somefunc ();
}

Where somefunc allocates space with alloca.  If you think about the
implementation details here, you'll realize that calls to alloca from
within somefunc called in this loop will all have the same stack
pointer.  Thus garbage will keep accumulating on the stack across
iterations of the loop.  To avoid that you put an alloca(0) in the loop
like this:

for (...) {
  somefunc ();
  alloca (0);
}

Now when we call alloca (0) the stack pointer will indicate that the
alloca calls that occurred within somefunc are all dead and thus the
alloca(0) will release memory.

Jeff



More information about the Gcc-patches mailing list