1

So I came across placement new recently, and I had a question regarding it. I do understand that placement new is used when you want to allocate an object on an already allocated memory.

Let's say I have a class called foo, which is 20 bytes.

I'd do some operations with it, and then I'll call a placement new for a class called bar, which is 10 bytes.

What happens to the last 10 bytes that is not part of the new object? Does placement new partition only the amount of memory required, which is in this case 10 bytes? Or does the pointer just carry around the extra 10 bytes until it is deallocated?

And another case, let's say I've first started by allocating memory for class bar, which is 10 bytes. I'll then placement new class foo, which is 20 bytes. Will the compiler allocate more memory? Or do I have to make sure to allocate enough memory beforehand?

Wandering Fool
  • 2,170
  • 3
  • 18
  • 48
dwnenr
  • 443
  • 1
  • 4
  • 15
  • 1
    _"is used when you want to allocate an object on an already allocated memory."_ - Not exactly. It's used when you want to instantiate an object at a specific place (i.e. memory location). It doesn't matter what the storage duration of the memory is. – Captain Obvlious Aug 14 '15 at 00:57
  • @CaptainObvlious Hm...strange. I've got the definition from here: http://stackoverflow.com/questions/222557/what-uses-are-there-for-placement-new – dwnenr Aug 14 '15 at 02:24

2 Answers2

1

What happens to the last 10 bytes that is not part of the new object.

Those extra bytes are still available for you to use. They will be deallocated properly only if you use the right deallocation method.

// Allocate memory.
char* buffer = new char[20];

// Construct a Foo using placement new
Foo* fooPtr = new (buffer) Foo;

// Use fooPtr
// ...

// Call the destructor for fooPtr explicitly.
// Don't call delete fooPtr. That will lead to
// undefined behavior.
fooPtr->~Foo();

// Now the memory is ready to be resued.

// Construct a Bar using placement new
Bar* barPtr1 = new (buffer) Bar;

// If there is enough space, you can use:
Bar* barPtr2 = new (buffer+sizeof(Bar)) Bar;

// Use barPtr1 and barPtr2
// ...

// Now call the destructor on the pointers explicitly.
barPtr1->~Bar();
barPtr2->~Bar();

// Deallocate the memory that corresponds to the method used to
// allocate it.
delete [] buffer;

And another case, lets say I've first started of by allocating memory for class bar, which is 10 bytes. I'll then placement new class foo, which is 20 bytes. Will the compiler allocate more memory?

No, the compiler won't allocate more memory. That will lead to undefined behavior.

R Sahu
  • 204,454
  • 14
  • 159
  • 270
  • About calling the destructor for the foo class before placement newing other objects. Is okay not to call the desctuctor if the class doesnt contain any allocated memory? Or are there some other stuff going on in the destructor, so I HAVE to call the destructor? – dwnenr Aug 14 '15 at 01:08
  • 2
    @dwnenr, You don't HAVE to call the destructor if it does not free up resources, such as deleting some of its own memory, closing file handles, etc. However, it is a good practice to call it. The call to the destructor does no harm at all if the destructor does not do anything but omiting it can potentially lead to resource leaks. – R Sahu Aug 14 '15 at 01:11
  • 1
    @dwnenr: and who is to say that in the future, you don't add something to the class that requires a destructor. Do you want to have to hunt down your existing usages of placement-new to add the destructor calls? Better to do the calls sooner rather than later and not have to worry about that. – Remy Lebeau Aug 14 '15 at 01:15
1

What happens to the last 10 bytes that is not part of the new object.

Nothing at all. Placement-new does not touch it. It would not know if something else already existed in that block of memory. You could easily allocate size for 2 bar objects, construct a bar object in the second 10 bytes, then construct another bar object in the first 10 bytes. Think of what would happen if placement-new did something to overstep the bounds of the memory address you provide and it corrupted the bar in the second half of the memory. Not good. So it doesn't do that.

Does placement new partition only the amount of memory required, which is in this case 10bytes?

Yes. Placement-new would simply call the bar constructor, passing it the specified memory address as the starting address for the constructor to initialize. The constructor would initialize only the portion of the memory it needs. Since the bar class is 10 bytes, no more than 10 bytes can be initialized. The remaining 10 bytes are untouched.

Or does the pointer just carry around the extra 10 bytes until it is deallocated.

If you allocate 20 bytes and construct a bar in the first 10 bytes, the remaining 10 bytes would simply exist after the bar object in memory, but not be part of the bar object itself. You can do whatever you want with those 10 bytes.

And another case, lets say I've first started of by allocating memory for class bar, which is 10 bytes. I'll then placement new class foo, which is 20 bytes. Will the compiler allocate more memory?

No. Placement-new simply constructs the specified class at the memory address you provide. It is your responsibility to ensure that memory is large enough to hold the class being constructed.

Or do I have to make sure to allocate enough memory beforehand?

Yes.

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
  • So if I first allcocated 20bytes, and placement new 10bytes. If I do not have a pointer to the 2nd half of the memory, will this cause memory leak? I've thought of accessing the 2nd half memory using *pointer + sizeof(class), but I'm not sure if this is the correct way to do so. – dwnenr Aug 14 '15 at 01:04
  • 1
    You have to maintain a pointer to anything you own - the 20-byte buffer, and the `bar` object (smart pointers is another topic of discussion). If you do not explicitly destruct the `bar` object, its members will be leaked (non-POD types, dynamically allocated objects, etc). If you do not deallocate the 20-byte buffer after you are done using it, it (and everything in it) will be leaked. In short, you always have to deallocate whatever you allocate, using the appropriate mechanism: `malloc()` -> `free()`, `new` -> `delete`, `new[]` -> `delete[]`, `placement-new` -> `explicit destructor`, etc. – Remy Lebeau Aug 14 '15 at 01:09
  • 1
    If you allocate 20 bytes and construct a 10-byte object at the beginning of it, you can certainly use `pointer + 10 bytes` to get a pointer to the second 10 bytes. That is basic pointer arithmetic, use of placement-new does not change that. – Remy Lebeau Aug 14 '15 at 01:11