tags:

views:

1275

answers:

5

Is there a way to use the new keyword to allocate on the stack (ala alloca) instead of heap (malloc) ? I know I could hack up my own but I'd rather not

+13  A: 

To allocate on the stack, either declare your object as a local variable by value, or you can actually use alloca to obtain a pointer and then use the in-place new operator:

void *p = alloca(sizeof(Whatever));
new (p) Whatever(constructorArguments);

However, while using alloca and in-place new ensures that the memory is freed on return, you give up automatic destructor calling. If you're just trying to ensure that the memory is freed upon exit from the scope, consider using std::auto_ptr<T> or some other smart pointer type.

Jeffrey Hantin
+7  A: 

Jeffrey Hantin is quite correct that you can use placement new to create it on the stack with alloca. But, seriously, why?! Instead, just do:

class C { /* ... */ };

void func() {
    C var;
    C *ptr = &var;

    // do whatever with ptr
}

You now have a pointer to an object allocated on the stack. And, it'll properly be destroyed when your function exists.

derobert
Your example is exactly what I meant by declaring it as a local variable by value.
Jeffrey Hantin
A: 

New is just an operator, so you could override it to do the above. I had the same reaction derobert, but I suppose the attraction is being able to allocate a variable amount of memory on the stack. Still, I can't see how you could ever make this work because the memory will be cleaned up as soon as you exit operator new(). Also Jeffrey's answer seems a little dangerous - I doubt the destructor will be called on that object when the function exits - can anyone confirm this?

BigSandwich
shared_ptr or scope_ptr, or even auto_ptr would do the trick
acidzombie24
You can't override it to allocate from _the stack_, as your operator new (when called) gets its own stackframe. Memory allocated from there will be freed once your operator new returns.
MSalters
I just said that MSalters:"Still, I can't see how you could ever make this work because the memory will be cleaned up as soon as you exit operator new()".
BigSandwich
@BigSandwich, you are absolutely right, destructors are not called automatically for objects allocated with alloca(). See my other answer about RAII and exceptions for other problems.
Carl Seleborg
+2  A: 

You could do:

Whatever* aWhatever = new ( alloca(sizeof(Whatever)) ) Whatever;

You could uses a RAII class to do the destruction I suppose (EDIT: Also see this other answer for more information on potential problems with this approach):

template <class TYPE>
class RAII
    {
    public:
        explicit RAII( TYPE* p ) : ptr(p) {}
        ~RAII() { ptr->~TYPE(); }
        TYPE& operator*() const { return *ptr; }
    private:
        TYPE* ptr;
    }

void example()
    {
    RAII<Whatever> ptr = new ( alloca(sizeof(Whatever)) ) Whatever;
    }

You could use a macro to hide the alloca.

Regards DaveF

David Allan Finch
+1  A: 

Be careful when using _alloca() with GCC

GCC has a bug which makes _alloca() incompatible with SJLJ exception handling in C++ (Dwarf2 is reported to work correctly). When an exception is thrown out of the function allocating the memory, the bug causes stack corruption before the destructors get to run. This means that any RAII class working on the allocated object(s) has to run in another function to work properly. The proper way of doing it looks like this:

void AllocateAndDoSomething()
{
  Foo* pFoo = reinterpret_cast<Foo*>(_alloca(sizeof(Foo)));
  new (pFoo) Foo;

  // WARNING: This will not work correctly!
  // ScopedDestructor autoDestroy(pFoo);
  // pFoo->DoSomething();

  // Instead, do like this:
  DoSomething(pFoo);
}

void DoSomething(Foo* pFoo)
{
  // Here, destruction will take place in a different call frame, where problems
  // with _alloca() automatic management do not occur.
  ScopedDestructor autoDestroy(pFoo);
  pFoo->DoSomething();
}
Carl Seleborg