alloca()
allocates memory on the stack rather than on the heap, as in the case of malloc()
. So, when I return from the routine the memory is freed.
still alloca use is discouraged, why?
I don't perceive such a consensus. Lots of strong pros; a few cons:
while
or for
loop) or in several scopes, the memory accumulates per iteration/scope and is not released until the function exits: this contrasts with normal variables defined in the scope of a control structure (e.g. for {int i = 0; i < 2; ++i) { X }
would accumulate alloca
-ed memory requested at X, but memory for a fixed-sized array would be recycled per iteration).inline
functions that call alloca
, but if you force them then the alloca
will happen in the callers' context (i.e. the stack won't be released until the caller returns)alloca
transitioned from a non-portable feature/hack to a Standardised extension, but some negative perception may persistmalloc
's explicit controlmalloc
encourages thinking about the deallocation - if that's managed through a wrapper function (e.g. WonderfulObject_DestructorFree(ptr)
), then the function provides a point for implementation clean up operations (like closing file descriptors, freeing internal pointers or doing some logging) without explicit changes to client code: sometimes it's a nice model to adopt consistently
WonderfulObject* p = WonderfulObject_AllocConstructor();
- that's possible when the "constructor" is a function returning malloc
-ed memory (as the memory remains allocated after the function returns the value to be stored in p
), but not if the "constructor" uses alloca
WonderfulObject_AllocConstructor
could achieve this, but "macros are evil" in that they can conflict with each other and non-macro code and create unintended substitutions and consequent difficult-to-diagnose problemsfree
operations can be detected by ValGrind, Purify etc. but missing "destructor" calls can't always be detected at all - one very tenuous benefit in terms of enforcement of intended usage; some alloca()
implementations (such as GCC's) use an inlined macro for alloca()
, so runtime substitution of a memory-usage diagnostic library isn't possible the way it is for malloc
/realloc
/free
(e.g. electric fence)On many systems alloca() cannot be used inside the list of arguments of a function call, because the stack space reserved by alloca() would appear on the stack in the middle of the space for the function arguments.
I know this question is tagged C, but as a C++ programmer I thought I'd use C++ to illustrate the potential utility of alloca
: the code below (and here at ideone) creates a vector tracking differently sized polymorphic types that are stack allocated (with lifetime tied to function return) rather than heap allocated.
#include
#include
#include
struct Base
{
virtual ~Base() { }
virtual int to_int() const = 0;
};
struct Integer : Base
{
Integer(int n) : n_(n) { }
int to_int() const { return n_; }
int n_;
};
struct Double : Base
{
Double(double n) : n_(n) { }
int to_int() const { return -n_; }
double n_;
};
inline Base* factory(double d) __attribute__((always_inline));
inline Base* factory(double d)
{
if ((double)(int)d != d)
return new (alloca(sizeof(Double))) Double(d);
else
return new (alloca(sizeof(Integer))) Integer(d);
}
int main()
{
std::vector numbers;
numbers.push_back(factory(29.3));
numbers.push_back(factory(29));
numbers.push_back(factory(7.1));
numbers.push_back(factory(2));
numbers.push_back(factory(231.0));
for (std::vector ::const_iterator i = numbers.begin();
i != numbers.end(); ++i)
{
std::cout << *i << ' ' << (*i)->to_int() << '\n';
(*i)->~Base(); // optionally / else Undefined Behaviour iff the
// program depends on side effects of destructor
}
}