On Thu, Aug 4, 2016 at 1:30 PM, Aldy Hernandez <al...@redhat.com> wrote: > Howdy! > > As part of my -Walloca-larger-than=life work, I've been running said pass > over gcc, binutils, and gdb, and trying to fix things along the way. > > Particularly irritating and error prone is having to free malloc'd pointers > on every function exit point. We end up with a lot of: > > foo(size_t len) > { > void *p, *m_p = NULL; > if (len < HUGE) > p = alloca(len); > else > p = m_p = malloc(len); > if (something) > goto out; > stuff(); > out: > free (m_p); > } > > ...which nobody really likes. > > I've been thinking that for GCC we could have a protected_alloca class whose > destructor frees any malloc'd memory: > > void foo() > { > char *p; > protected_alloca chunk(50000); > p = (char *) chunk.pointer(); > f(p); > } > > This would generate: > > void foo() () > { > void * _3; > > <bb 2>: > _3 = malloc (50000); > f (_3); > > <bb 3>: > free (_3); [tail call] > return; > } > > Now the problem with this is that the memory allocated by chunk is freed > when it goes out of scope, which may not be what you want. For example: > > func() > { > char *str; > { > protected_alloca chunk (99999999); > // malloc'd pointer will be freed when chunk goes out of scope. > str = (char *) chunk.pointer (); > } > use (str); // BAD! Use after free. > }
But how's that an issue if the chunk is created at the exact place where there previously was an alloca? Your class also will not work when internal_alloc is not inlined and the alloca path is taken like when using non-GCC host compilers. > In the attached patch implementing this class I have provided another idiom > for avoiding this problem: > > func() > { > void *ptr; > protected_alloca chunk; > { > chunk.alloc (9999999); > str = (char *) chunk.pointer (); > } > // OK, pointer will be freed on function exit. > use (str); > } > > So I guess it's between annoying gotos and keeping track of multiple exit > points to a function previously calling alloca, or making sure the > protected_alloca object always resides in the scope where the memory is > going to be used. > > Is there a better blessed C++ way? If not, is this OK? It looks like you want to replace _all_ alloca uses? What's the point in doing this at all? Just to be able to enable the warning during bootstrap? Having the conditional malloc/alloca will also inhibit optimization like eliding the malloc or alloca calls completely. Thanks, Richard. > Included is the conversion of tree.c. More to follow once we agree on a > solution. > > Tested on x86-64 Linux. > > Aldy