3

There is such code:

#include <iostream> int main() { int a; int* p = new (&a) int(2); std::cout << a << std::endl; // delete p; error BLOCK TYPE IS INVALID std::cin.get(); return 0; } 

The output is:

2 

Why is it possible to dynamically allocate memory on stack? (I thought that heap is the right place to do this). And, why does delete operator return error in this case, but new operator work?

3
  • You're doing placement new, so you are reusing a's memory to place p into it. Commented Sep 18, 2011 at 14:25
  • 1
    It's not really dynamic as the maximum space you have to use is 'sizeof(int)' Commented Sep 18, 2011 at 14:26
  • see linux alloca Commented Aug 16, 2019 at 6:33

4 Answers 4

8

This is using the placement new syntax. Placement new does not allocate memory at all, rather, it is a way to construct an object at a particular location. In this example, the memory comes from the stack. It doesn't have to. delete has issues because you didn't new the memory.

There are ways to dynamically allocate memory from the stack (alloca) but that's not what is happening here.

Sign up to request clarification or add additional context in comments.

Comments

7
int* p = new (&a) int(2); 

This is called placement-new. It doesn't allocate memory. It constructs the object in the same memory of a. In placement new, it's the user who specifies the memory region where new operator constructs the object. In your code above, you specify the memory region by writing (&a) expression just after the new keyword. Since &a is not a dynamically allocated memory, you cannot delete it:

delete p; //runtime-error 

It would give runtime error, it attempts to delete the memory where the variable a resides.

However, if you dynamically allocate the memory, then you can do delete it. Lets suppose, A is some class, then you should be doing this:

char *buffer = new char[sizeof(A)]; //allocate memory of sizeof(A); ///ASSUMPTION: the buffer is properly align as required by the type A //use placement-new to construct an object at the specified memory region A *pA = new (buffer) A(/*..parameters..*/); //... //incorrect way to delete the memory! //delete pA; //incorrect //before deleting the memory you should be calling the destructor explicitly as pA->~A(); //call the destructor explicitly - must do it //now deallocate the memory as delete []buffer; 

This is simplest example of placement-new which explains the syntax only. But the story doesn't end here; it is the beginning and to make it work properly, the memory pointed to by buffer has to be aligned properly for the object type, and in the above example, I simply assumed so. In the real code, you cannot make such dangerous assumption. Now read this FAQ:

Comments

3

This is called placement new: http://www.parashift.com/c++-faq-lite/dtors.html#faq-11.10

You can optionally pass an address to new, and it will only call the object's constructor (if it has one). Because no memory was allocated, it would be an error to deallocate it with delete. Simply call the object's destructor (if it has one) and you're done.

Comments

2

C++ separates the notions of memory allocation and object lifetime. This is perhaps one of the most important "new" aspects of the language compared to C. In C there is no such distinction because variables are entirely determined by their memory, while in C++ objects have a more abstract notion of a "state" which is distinct from the underlying memory.

Let's look at memory first:

{ char buf[100]; // automatic allocation, scoped lifetime } { void * p = std::malloc(100); // dynamic allocation, manually managed void * q = ::operator new(100); // essentially identical // ... ::operator delete(q); // manual deallocation std::free(p); // ditto } 

On the other hand, an object's lifetime is a separate topic:

{ Foo x; // automatic storage, scoped lifetime. // Implies automatic memory allocation for sizeof(Foo) bytes. } { Foo * px = ::new Foo; // dynamic storage, manual lifetime, // implies dynamic allocation via ::operator new() Foo * py = ::new (q) Foo; // dynamic storage and manual lifetime, uses memory at q // ... delete px; // destroy object _and_ deallocate memory py->~Foo(); // destroy object. Memory was never our business to start with. } 

As you can see, the separation of memory and object lifetime adds a lot of flexibility: We can have dynamic objects living in automatic memory, or take care of allocation ourselves and reuse memory for repeated object constructions. The standard new and delete expressions combine allocation and construction, but this is only a shortcut for the most frequently used operations. In principle, you're entirely free to handle memory and object lifetime separately.

This idea underpins the notion of allocators, which are a core concept in the C++ standard library.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.