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.
Related
I wanted to ask, is dynamically creating a pointer, and then changing a pointer address to something else still deleting the original allocated space?
for example:
int main()
{
int c = 50;
// Memory leak
int * q = new int;
q = & c;
delete q;
}
What exactly is getting deleted or happening?
Thanks!
What exactly is getting deleted or happening?
Memory leaking and undefined behaviour.
When you do q = & c; you are losing your only tracking of the memory allocated by new int. Noone keeps track of this for you, there is no garbage collector, it is simply lost and cannot be recovered.
When you then do delete q; (where q is assigned to &c) you are deleting memory that you didn't allocate, and worse you are deleting memory on the stack. Either of these will result in undefined behavior.
This is an excellent preface into why you should avoid using pointers in circumstances where you don't need them. In this case, there is no reason dynamically allocate your int. If you really need a pointer, use a c++11 smart pointer (or boost if you don't have c++11). There are increasingly rare cases where you really do need a raw c type pointer. You should read Effective Modern c++ Chapter 4 for excellent detail on this subject.
is dynamically creating a pointer, and then changing a pointer address to something else still deleting the original allocated space?
No. delete will deallocate the memory to which its operand points. You must delete the same block of memory that you obtained from new.
int c = 50;
int * q = new int;
int * r = q;
q = & c;
delete q; // WRONG! q points to something you didn't get from new
delete r; // OK! p points to the block you got from new
To be even more clear, delete doesn't care about what variable it operates on, it only cares about what that variable points to. In the last line above, r points to the block that was originally pointed to by q and allocated by new, so you can safely delete it. q points to statically allocated memory, not something you got from new, so you can't delete it.
Instead of changing where q points, though, you can copy the value you want into the space that q points to:
int c = 50;
int * q = new int;
*q = c;
delete q; // OK! q still points to the same place
Here you're changing the value stored in the location to which q points, but you're not changing q itself. q still points to the block you got from new, so it's safe to delete it.
You code will (try to) delete c. There's no memory management or anything like that in C/C++. delete will try to delete whatever the given pointer points to, and and whatever is not deleted (either by calling delete for variables created with a call to new, or by leaving the scope for local variables) will remain in memory until the program ends.
Notice that trying to delete a local variable will propably cause a crash, since delete actually checks (in a very basic manner) what it deletes - at least to know how much memory has actually been allocated at that address. And at this check, it will propably notice that c doesn't include this information, or that it isn't even at the right end of the memory space, so it will crash.
It will crash because c is created in the stack memory section. If you're lucky and the program didn't crash you aren still leaking memory because the q reference is lost.
First answer is to your question:-
I wanted to ask, is dynamically creating a pointer
We don't create a pointer dynamically. Pointers are just a variable like other variable in C and C++. Difference is, pointer is a variable which can store the address of a particular memory location. In run time you just dynamically allocate memory and assign the address of first address location of that memory size into it.
Now what will happen if you don't delete/free the memory and assign a new address to it. In that case memory will not be release/freed and that can not be use anymore as that will never be marked as free by OS. When you free/delete memory O/S mark that area as free to use, and your running process can utilize it in future. That is call proper memory management. Improper memory manage leads your program to memory leak.
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
I've read the post: Why do we need to set rvalue reference to null in move constructor?
It said that during a move, you just copied the pointer from one object to another, so two pointers points to the temporary object. And when the temporary object goes out of scope, its destructor will run. And then the object pointed by 2 pointers would be deallocates. So the pointer field of object constructed by move constructor would point to unavailable place.
However, look at following code:
int *p = new int(3);
int *q = p;
delete p;
std::cout << *q << std::endl;
after delete the pointer p, pointer q could still access the int object.
So, is that just because when the object is accessed by rvalue reference causes the difference?
No you can't. It appears to work, but it's entirely undefined behavior. The memory is released to the runtime.
When you move something, you're effectively saying the original object is no longer valid - you only access its original contents from the moved-to object. Furthermore, the set to NULL after a move prevents a double-delete - when the original objects goes out of scope and attempts to free that memory, it will either fail straight away (if the new object already free'd it) or the new object will fail when it itself attempts to release that memory.
Accessing deleted memory of the free store is undefined behavior.
On move construction, the pointer of the object constructed is set to the pointer of the rvalue, which in turn is set to nullptr afterwards.
The object referenced by the rvalue ends its lifetime thereafter, after all it is a temporary. Therefore, the pointer set to nullptr is not expected to be used anymore. When it is destructed, delete nullptr; is executed, i.e., a no-op.
OTOH, when the lifetime of the constructed object ends, the actual resource is deleted - the pointer to it was assigned in the move constructor.
No, after delete the pointer p, pointer q cannot still access the int object. If you think otherwise because you ran it and got 3 in the output--that's because you caused undefined behavior and UB can "work" as one of its many, many options.
In general what happens is that the memory address hasn't been reused yet, still belongs to the program (so it has permission to access and the value has not been erased), so you'll see whatever value was deleted in that memory. All this means that it will appear as if the code is perfectly OK when it's not. You could also print using *p in this case and it would be no different. The p and q variables both contain the same address...which was freed by a delete.
One interesting aspect of this is that high security applications, or encryption applications like GPG, manually fill deleted memory with garbage so that it can't just be sniffed out--giving access to private keys out to the world. Otherwise the key would still just be written in RAM until someone writes something else there!
This is the problem with pointers. They do not convey ownership semantics.
You should be using something like std::unique_ptr. When you move the pointer from one object to another the old object recognizes it no longer owns the object and thus you can;t access the data.
Simple solution. Like the rest of the C++ community stop using pointers like this.
std::unqieu_ptr<int> p(new int(3));
std::unique_ptr<int> q = p; // Fails to compile
std::unqieu_ptr<int> p(new int(3));
std::unique_ptr<int> q = std::move(p); // explicitly transfer ownership.
// delete p; // No longer need this as when the onbject goes out of scope
// it is deleted.
Both the question you linked and your question is trying to avoid undefined behavior upon dereferencing of q.
The thing is that, (in the linked question) you have to know that you can't dereference q anymore (you aren't managing it) by setting it to nullptr. But here, it's your business to not to dereference q after the delete. It's extremely predictable that q will be deleted before std::cout << *q << std::endl;. It's your fault that you're dereferencing it!
Nevertheless, setting q to nullptr helps with debugging, delete q is no longer UB, and nullptr signifies a pointer to non-existent object.
I have a few silly questions (probably for most), it's less about 'how' do I do them and more about 'why' do they work this way? I know you are not supposed to ask multiple questions, but these are fairly small and related to one topic. Seems like it'd be a waste to separate them out.
I understand for the most part pointers, and the operators themselves. (Although I am curious why the * is called the de-reference operator, since isn't it referring to a reference of what it contains?)
I.e:
int x = 25;
int *p = &x;
So & makes sense, since *p is a place in the stack of type int that contains the address of x (which we know is 25).
So by saying *p are we 'referencing' the address of p which is pointing to the 25. Maybe it's just an English semantics thing? Maybe someone can explain why it's called 'de-reference'?
Take this valid code sample:
int *p = new int;
*p = 5
Simple enough, we're making a new place in the stack with the size of an int pointer (whatever that may be). p will contain some address that has a 5 for a value.
Thing is, I haven't actually declared anything that's storing a 5, so what the heck is p pointing to? I mean, this does indeed work, but I never made a int x = 5 or anything like that, and gave the address to p to point to? How does it even know?
p contains an address that points to something, but I never made that 'address' it's pointing to? Does the compiler just know to create another address somewhere else? (Sorry if this is a really stupid question.)
I was reading on here about some memory leaks on another question:
A *object1 = new A();
pretending A is a class first of all. Someone was saying the object1 stores the value of A. Isn't that incorrect? Doesn't object1 store the address of what new A() created and is pointing to it?
Because delete object1 deletes the pointer, which points to the new A() (but from the other question delete object1 would indeed be the correct syntax. So does that leave the new A() hanging out there? Or does it get automatically deleted? (As you can tell I'm a bit confused.)
If delete object1 does indeed delete what the pointer is pointing to and not the pointer itself, doesn't this just leave a dangling pointer?
Here
int x = 25;
int *p = &x;
* is not the dereferencing operator. It's part of the type of p. It basically says that p is a pointer.
Here
int *p = new int;
*p = 5;
The key is new int. It dynamically creates an int and returns it's address, so p now points to that address. *p = 5 (btw, here * is the dereferencing operator) modifies the value -- of that dymanically allocated int -- to 5
Indeed object1 holds the address of the newly created A. Since we're here we should clarify this: A is a (user defined) type. So it makes no sense to say that A has a value. Objects of type A have value.
delete p doesn't delete a pointer. It does 2 things:
Destroys an object created by a new-expression
Deallocates storage previously allocated by a matching operator new
The pointer isn't actually changed, i.e. it still points to the same address. Only now that address isn't allocated, i.e. can't be dereferenced anymore.
You can further refer to this SO answer - Static, automatic and dynamic storage duration to further understand objects, pointers, new/delete.
1: I'm not sure what you're implying when you say "which we know is 25". The address of x is not 25, rather that is the value of x. You do not set the address of x in a statment like int x = 25
But to answer your question, p is a reference, which is to say its value is an address. Accessing the value stored at the address p requires the *p, which dereferences the pointer.
2: You have allocated memory for p; you executed a new. You have allocated 4 (or 8) bytes of memory for a new integer on the heap, so p is pointing to a newly allocated block of memory. Saying *p = 5; tells the compiler to set the value stored at that address to 5.
3: Your assumption is correct; object1 does not store the value of a new A, rather points to a block of memory equivalent in size to aninstance of an object of size A.
delete object1; Does not delete the pointer. The pointer is simply an integer on the stack, rather it gives back the allocated memory for that pointer back to the system. A as you knew it is deleted, but the pointer still exists, and using it at this point is undefined behavior. You are correct in assuming you have a dangling pointer now, that is why you should always set deleted pointers to NULL.
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.