I have few questions about the placement new while reading the C++ Primer Plus.
The sample code in the book is like this:
class JustTesting{
private:
string words;
int number;
public:
JustTesting(const string & s = "Just Testing", int n = 0){
number = n;
words = s;
//some code here
}
~JustingTesting(){}
};
char * buffer = new char[BUF]; //get a block of memory
JustTesting *pc1, *pc2;
pc1 = new (buffer) JustTesting; //Place object in buffer
pc2 = new JustTesting("Heap1",20); //Place object on heap
//some code
JustTesting *pc3, *pc4;
pc3 = new (buffer) JustTesting("Bad Idea", 6);
pc4 = new JustTesting("Heap2", 10);
//some code
delete pc2; //free Heap1
delete pc4; //free Heap2
pc3->~JustTesting(): //Does the order of these two destructor call
pc1->~JustTesting(); // matters?
delete[] buffer; //free buffer
The author says, we cannot use
delete pc1;
or
delete pc3;
to delete the objects they pointing to, because delete works in conjunction with new but not with placement new. For example, the pointer pc3 does not receive an address returned by new, and delete pc3 will result in a runtime error.
The questions are:
first, will the object pointed to by pc3 overwrite the one pointed to by pc1? If no, how could two different objects stay in a same address. If yes, why we still possible to call the destructor explicitly(pc1->~JustTesting();) to free the object's memory.
question two: Does the order of these two explicit destructor call matter?
question three: What is the meaning of "the pointer pc3 does not receive an address returned by new"? Is the address returned by new different with the address given by assignment?
Thank you!
Everything is right, until...
pc3 = new (buffer) JustTesting("Bad Idea", 6);
This invokes undefined behaviour (no?). You've already constructed an object of type JustTesting at buffer, but you have not destructed it! At the same time, you're creating yet another object at the same location. Then, the first object becomes corrupted (althought, in standardese minds, it still exists in a parallel universe).
You can't perform delete on a pointer to anything that hasn't been allocated (and constructed) by operator new. Similarly, you can only destroy and deallocate an array created by operator new[] with operator delete[].
Now, "placement new" is just a fancy name for a direct call to a constructor. Thus, new(buff) Type(...) is just a call to Types constructor with this set as buff. And, simmetric with what said above, you can only destroy what has been constructed.
If you use automatic storage, operator new, or whatever other implicit-RAII-conformant means that is responsible for allocating, constructing, and destructing your objects automatically (or when you specify it shall be done), then calling an object's destructor in such a context will lead to the destructor being called twice, a.k.a undefined behaviour.
Now, it happens that you (shall I repeat it again? you!) are the one who decides when and how to obtain the memory for the object, then the environment has no change of guessing when to either destroy or deallocate the object. Thus, once you call the object's destructor explicitly, the memory that once contained it is under your responsibility for being freed, somehow, if at all.
Think of it as such. An expression of the form ptr = new X(...) can be perfectly implemented as...
ptr = malloc(sizeof(X));
new(ptr) X(...);
And operator delete becomes...
ptr->~X();
free(ptr);
The questions are: first, will the object pointed to by pc3 overwrite the one pointed to by pc1?"
This is dangerous, both objects will be attempting to share the same block of memory.
If yes, why we still possible to call the destructor explicitly(pc1->~JustTesting();) to free the object's memory.
This does not free the memory of an object created via placement new. It simply calls the destructor of the object. The conventional delete operator will call the destructor, then attempt to free the memory by assuming it was allocated normally. In this example, it will effectively try to call a destructor on that block of memory twice, due to the sharing issue that has already been raised.
question two: Does the order of these two explicit destructor call matter?
No, in either case, the second call is likely to have issues.
question three: What is the meaning of "the pointer pc3 does not receive an address returned by new"? Is the address return by new different with the address given by assignment?
The address returned by new is a block of freshly allocated memory from the heap (assuming the default new operator hasn't been overridden). The address returned by placement new is simply the address of the block of memory you gave to it.
first, will the object pointed to by pc3 overwrite the one pointed to by pc1?
Yes. They will both be stored at the address pointed to by for buffer. This may be undefined behaviour, and is generally a bad idea anyway (unless you know for sure that the class's destructor doesn't do anything important).
If yes, why we still possible to call the destructor explicitly(pc1->~JustTesting();) to free the object's memory.
Most likely, pc1 and pc3 point to the same location. I'm not sure if that's guaranteed, but I can't imagine why it would not be the case on any implementation.
If pc1 and pc3 point to the same location, then this question is like asking why the following code works:
char *p1 = new char[50];
char *p2 = p1;
delete [] p2;
What is the meaning of "the pointer pc3 does not receive an address returned by new"? Is the address return by new different with the address given by assignment?
Bad wording probably. Clearly pc3 does receive an address returned by new - you can see it right there in the code:
pc3 = new // ... other stuff ...
I suspect they mean that the address was not allocated by new. Normally new allocates a block of memory to hold an object, and then constructs an object in that memory block. With placement new, it only constructs an object in the provided memory block.
Likewise, delete will destroy the object whose pointer was passed to it, and then free a memory block that was previously allocated at that address. deleteing an object not allocated with new is undefined behaviour - think of JustTesting a("Object on stack", 30); delete &a;.
If you're lucky, delete pc3 might have the same effect as pc3->~JustTesting(); delete [] buffer;, so it might not crash - although then delete [] buffer; would crash later since you're deleting an object twice. You definitely should not rely on that. The only safe thing to do is to not delete the objects allocated with placement new.
The questions are: first, will the object pointed to by pc3 overwrite the one pointed to by pc1?
Yes.
If yes, why we still possible to call the destructor explicitly(pc1->~JustTesting();) to free the object's memory.
pc does not already exist, any function invoking on it is UB.
question two: Does the order of these two explicit destructor call matter?
You shouldn't call them together at all.
question three: What is the meaning of "the pointer pc3 does not receive an address returned by new"? Is the address returned by new different with the address given by assignment?
I think it should mean "the pointer pc3 does not receive an address returned by newly allocated". The placement new just return the address you passed to it.
Related
I have a member function that I call, from there I get a pointer to a private member which is of class BankAccount, I am unsure what happens with the pointers when I deallocate them. I create a new pointer and heap memory address but then assign the pointer to something else. What does "delete" end up deleting?
I read that if you delete a pointer
Here is the code
void Employee::raise(){
BankAccount* tempBank = new BankAccount(); //set pointer to new heap place
double amt;
tempBank = get_bank(); // set pointer to existing heap implicitly
amt = tempBank->get_amount();
amt = (amt + (amt/12));
tempBank->set_amount(amt);
delete tempBank; //does this delete new heap created or does it add a new block of
//memory to heap since it is trying to delete a pointer assigned
//by memory address
tempBank = NULL;
}
I realized I could just do the code below to avoid this situation, but now I am curious as to what happens in the above situation with the memory
BankAccount* tempBank = get_bank();
So what exactly happens when delete is called in my original situation?
When you use delete ptr; the object pointed to by ptr is destroyed and the corresponding memory is returned to the memory management system. The variable ptr and any copy thereof hold a bit pattern referring to now inaccessible memory (the system may still allow you to actually access this memory and it may even still contain the original data but that's undefined behavior and you shall not rely on it).
Put differently, the memory deallocation does not affect the pointer but it does affected the pointed to entity. In your case, the BankAccount, i.e., the result of *tempBank gets destroyed while the pointer tempBank remains unchanged by the delete operation. Obviously, setting tempBank to NULL does change this specific pointer but none of the other copies (if any), giving you false sense of security: I'd not set deleted pointers to NULL unless I keep them around for whatever reason...
Pointers are essentially just the address of the first byte in memory that belongs to the data structure they point to. So in your case:
BankAccount* tempBank = new BankAccount(); // this creates a new object of type BankAccount
// the pointer tempBank points to the first byte of that object in memory
tempBank = get_bank(); // now tempBank points to the first byte of whatever is returned from get_bank()
// that means that you no longer know the address of the object you created above (tempBank now points to something different)
// C++ has no garbage collection, so you just leaked that memory
delete tempBank; // you delete the object that was returned from get_bank
// so that memory is now marked as free and can be reused by whatever needs it
tempBank = NULL; // this is good style, you should always do it, but it does nothing to any allocated memory
BTW: using plain new and delete and owning raw pointers is considered bad style in modern C++. YOu might want to consider using std::shared_ptr or std::unique_ptr (or their boost equivalents if you cannot use C++11 yet)
I found this information that may be useful to you:
ordinary delete Deallocates the memory block pointed by ptr (if not null), releasing the storage space previously allocated to it by a call to operator new and rendering that pointer location invalid.
You can find more information in the original url: http://www.cplusplus.com/reference/new/operator%20delete/
delete tempBank;
when delete is called on pointer , it releases memory pointed by that variable[tempBank].
There are two notions of delete in C++: One is the operator, declared as ::operator delete(void*), which basically only frees up the memory and isn't usually thought about by most programmers. The other is the delete expression, delete p;, where p is a T*. The expression invokes the destructor of the object pointed to by p (and then frees the memory), which is a crucial language feature of C++ that has no analogue in C.
Well first of all, you are allocating from heap with your first exp which is
BankAccount* tempBank = new BankAccount();
and you lose the address of it with assigning another object address to tempBank pointer by
tempBank = get_bank();
so actually when you delete tempBank; you actually deleting the object that you allocated in the function get_bank(). Also because you have lost the address of object that you allocated with new BankAccount(), there is no more way to delete it, because you do not know the address of this object.
In your question, Are you sure that get_bank() indeed returns pointer to object allocated on heap (and not address of just plain object on stack). You have not mentioned it clearly hence it's worth to confirm it again. Now, coming back to question, if get_bank() returned pointer to private member which let's say was not on heap - in that case doing doing tempBank will result in undefined behavior because you can only invoke delete on an object which was created using new. But if get_bank() returned pointer to object allocated on heap then it will free memory of that object and then accessing that object from any other member function could become a nightmare!
You can check below link for some more related information,
Calling delete on variable allocated on the stack
Say I have the following code in a C++ program:
Object a = Object(someParameters);
new (&a) Object(someOtherParameters);
My assumption is that it replaces the contents of a with Object(someOtherParameters), avoiding a possible operator= declared for Object. Is this correct?
It's called placement new. It calles the constructor on the specified memory rather than allocating new memory. Note that in this case you have to explicitly call the destructor of your object before freeing the allocated memory.
Clarification. Suppose you have allocated some raw memory
char * rawMemory = new char [sizeof (Object)];
and you want to construct an object on that memory. You call
new(rawMemory) Object(params);
Now, before freeing the memory
delete [] rawMemory;
you will have to call the derstuctor of Object explicitly
reinterpret_cast<Object*>(rawMemory)->~Object();
In your particular example, however, the potential problem is that you haven't properly destroyed the existing object before constructing a new one in its memory.
Bonus:
Ever wondered how standard std::vector can do without its contained objects being default-constructible? The reason is that on most, if not all, implementations allocator<T> does not store a T* p which would require T to be default-constructible in case of p = new T[N]. Instead it stores a char pointer - raw memory, and allocates p = new char[N*sizeof(T)]. When you push_back an object, it just calls the copy constructor with placement new on the appropriate address in that char array.
It's known as placement new: it constructs the new Object at the address given inside the parentheses. Placement new is usually used to create an object in raw memory. Constructing a new object on top of an existing one, as this code does, is a bad idea, because it doesn't call the destructor on the original object.
I am new to C++, and now am studying new and delete keywords.
Point ppaa = *new Point;
Point *p = &ppaa;
ppaa.xpos = 1;
ppaa.ypos= 3;
delete &ppaa;
delete p;
Could you please explain why I cannot delete the ppaa above using &ppaa?
I know that delete can only operate on pointer, but I cannot understand why above is not possible since they are actually memory locations. Searching similar questions, it seems that this is related to the copying operations that happen at the first line, but I do not have good explanations.
T t = x;
is known as Copy Initialization. It:
It tries to convert x to an object of type T &
Then copies over that object into the to-initialized object t.
So your code statement,
Point ppaa = *new Point;
Creates a Point obejct on freestore/heap and
then copies that object to create a stack object ppaa.
Both these objects are different objects.
As you can see, You do not have any pointer to the heap object anymore after executing this statement.
You need to pass the address returned by new to delete in this case, Since you do not have the address anymore it results in memory leak.
Further, Note that &ppaa does not return the address returned by new it returns the address of the object ppaa located on the stack. Passing this address to delete results in Undefined Behavior because ppaa was never allocated on freestore/dynamically it is a stack based local/automatic object.
Assume you have an object of class Fool.
class Fool
{
int a,b,c;
double* array ;
//...
~Fool()
{
// destroys the array..
delete[] array ;
}
};
Fool *fool = new Fool() ;
Now, I know you shouldn't, but some fool calls the destructor on fool anyway. fool->~Fool();.
Does that mean fool's memory is freed, (ie a,b,c are invalid) or does that mean only whatever deallocations in ~Fool() function occur (ie the array is deleted only?)
So I guess my question is, is a destructor just another function that gets called when delete is called on an object, or does it do more?
If you write
fool->~Fool();
You end the object's lifetime, which invokes the destructor and reclaims the inner array array. The memory holding the object is not freed, however, which means that if you want to bring the object back to life using placement new:
new (fool) Fool;
you can do so.
According to the spec, reading or writing the values of the fields of fool after you explicitly invoke the destructor results in undefined behavior because the object's lifetime has ended, but the memory holding the object should still be allocated and you will need to free it by invoking operator delete:
fool->~Fool();
operator delete(fool);
The reason to use operator delete instead of just writing
delete fool;
is that the latter has undefined behavior, because fool's lifetime has already ended. Using the raw deallocation routine operator delete ensures that the memory is reclaimed without trying to do anything to end the object's lifetime.
Of course, if the memory for the object didn't come from new (perhaps it's stack-allocated, or perhaps you're using a custom allocator), then you shouldn't use operator delete to free it. If you did, you'd end up with undefined behavior (again!). This seems to be a recurring theme in this question. :-)
Hope this helps!
The destructor call does just that, it calls the destructor. Nothing more and nothing less. Allocation is separate from construction, and deallocation from destruction.
The typical sequence is this:
1. Allocate memory
2. Construct object
3. Destroy object (assuming no exception during construction)
4. Deallocate memory
In fact, if you run this manually, you will have to call the destructor yourself:
void * addr = ::operator new(sizeof(Fool));
Fool * fp = new (addr) Fool;
fp->~Fool();
::operator delete(addr);
The automatic way of writing this is of course Fool * fp = new Fool; delete fp;. The new expression invokes allocation and construction for you, and the delete expression calls the destructor and deallocates the memory.
Does that mean fool's memory is freed, (ie a,b,c are invalid) or does
that mean only whatever deallocations in ~Fool() function occur (ie
the array is deleted only?)
Fool::~Fool() has zero knowledge about whether the Fool instance is stored in dynamic storage (via new) or whether it is stored in automatic storage (i.e. stack objects). Since the object ceases to exist after the destructor is run, you can't assume that a, b, c and array will stay valid after the destructor exits.
However, because Fool::~Fool() knows nothing about how the Fool was allocated, calling the destructor directly on a new-allocated Fool will not free the underlying memory that backs the object.
You should not access a, b, and c after the destructor is called, even if it's an explicit destructor call. You never know what your compiler puts in your destructor that might make those values invalid.
However, the memory is not actually freed in the case of an explicit destructor call. This is by design; it allows an object constructed using placement new to be cleaned up.
Example:
char buf[sizeof (Fool)];
Fool* fool = new (buf) Fool; // fool points to buf
// ...
fool->~Fool();
The easiest place to see that the destructor is distinct from deallocation via delete is when the allocation is automatic in the first place:
{
Fool fool;
// ~Fool called on exit from block; nary a sign of new or delete
}
Note also the STL containers make full use of the explicit destructor call. For example, a std::vector<> treats storage and contained objects lifetime quite separately.
Can we call delete on the pointer which is allocated with the placement new? If no then why? Please explain in details.
I know that there is no placement delete. But I wonder why just delete opetator can not delete the memory without caring how that memory on which the pointer points is allocated?
delete is doing two things:
Calls destrucor
Frees memory
And I see no reaason for delete not to be able to call either of these two operations on the object which was created by placement new. Any idea about reasons?
You must only call delete on pointers that were created with operator new. If you use placement new with a memory location that was allocated by the normal operator new then you may safely use delete on it (provided you get the types and pointers right). However, you can use placement new on any memory, so you usually will manage that memory some other way and call the object's destructor manually.
For instance, in this convoluted and usually unnecessary scenario, it is safe to delete the memory you used placement new on, but only because you allocated it with new before:
char* mem = new char[sizeof(MyObject)];
MyObject* o = new (mem) MyObject;
// use o
o->~MyObject(); // with placement new you have to call the destructor by yourself
delete[] mem;
However, this is illegal:
char mem[16]; // create a buffer on the stack, assume sizeof(MyObject) == 16
MyObject* o = new (mem) MyObject; // use stack memory to hold a MyObject
// note that after placement new is done, o == mem
// pretend for this example that the point brought up by Martin in the comments didn't matter
delete o; // you just deleted memory in the stack! This is very bad
Another way to think of it is that delete only deallocates memory allocated previously by the normal new. With placement new, you do not have to use memory that was allocated by the normal new, so with the possibility of not having been allocated by normal new, delete cannot deal with it.
EDIT1: I know that there is no placement delete. But I wonder why just
delete opetator can not delete the memory without caring how that
memory on which the pointer points is allocated?
Because each flavour of memory allocation uses some implementation specific tracking of the memory (usually a header block that precedes the user address) and this make the allocation/deallocation to work only when paired up correctly:
new must pair with delete
new[] must pair with delete[] (most implementations though forgive mixing the newand new[])
malloc and frieds must pair with free
CoTaskMemAlloc pairs with CoTaskMemFree
alloca pairs with nothing (stack unwinding takes care of it)
MyCustomAllocator pairs with MyCustomFree
Attempting to call the wrong deallocator will result in unpredictable behavior( most likely seg fault now or later). Therefore calling delete on memory allocated by anything else other than new will result in bad things.
Furthermore the placement new may be called on any address, may not even be an allocated address. It can be called on an address located in the middle of some larger object, it may be called on a memory mapped region, it may be called on a raw virtual committed region, anything goes. delete woul attempt, in all these cases, to do what its implementation tell him to do: subtract the header size, interpret it as a new header, link it back into the heap. Kaboom.
The one that know how to release the memory of a placement new address is you, since you know exactly how was that memory allocated. delete will only do what it knows, and it may not be the right thing.
No, since delete not only calls the destructor but also frees the memory, but if you used placement new you must have allocated the memory yourself using malloc() or stack. You do, however, have to call the destructor yourself. Also see the C++ FAQ.
No. There is no placement-delete expression.
Typical scenario:
void * const addr = ::operator new(sizeof(T)); // get some memory
try {
T * const pT = new (addr) T(args...); // construct
/* ... */
p->~T(); // nap time
}
catch (...) {
}
::operator delete(addr); // deallocate
// this is _operator_-delete, not a delete _expression_
Note that the placement-new operator does have a corresponding delete operator which is mandated to be precisely void ::operator delete(void* [, size_t]) { }, a no-op; this is what gets called if the constructor of T throws an exception.
No, because a placement new doesn't allocate any memory. You use placement new on previously allocated raw memory. The only thing it does is call the constructor of the object.