Suppose I have the dynamic memory allocation through p1 as follows,
int* p1 = new int;
*p1 = 1;
I know that the memory referenced by p1 can be freed by using
delete p1;
p1 = nullptr;
But I wonder if there is another pointer p2 pointing at 1, can I delete this pointer in order to free the memory? And what would happen to pointer p1? In addition, what is the relationship between p1 and p2 essentially? For example,
int* p1 = new int;
*p1 = 1;
int* p2 = p1;
// Can I delete p2 like this? And what would happen to p1?
delete p2;
p2 = nullptr;
You can delete p2, but dereferencing p1 will result in undefined behavior, and possible segmentation fault.
It works like this:
Memory is allocated at some address.
Both p1 and p2 pointing to this memory location.
Once p2 deleted - p1 is still pointing to this memory location.
There is no leak, and everything is alright - just don't dereference p1. You can freely do p1 = nullptr, but can't *p1 = 1. Also, you cannot delete p1, since it's deleted already, and you'll probably catch segfault.
you're describing a very known problem in (old) C++ : when several pointers point to the same dynamic memory, which one deletes it?
if you delete both p1 and p2 you double delete the memory, which have undefined behavior (a crash, in the best case), if you delete p1 or p2 and you keep using the memory via the other pointer - you are using dangling pointer, which is undefined behavior (a crash, in the best case).
you need to make sure that when one pointer is deleted - you are not to use that memory in other pointers.
C++11 introduced a standard way of dealing this problem: using a self counting pointer, which only the last pointer deletes the memory:
auto p1 = std::make_shared<int>(0);
auto p2 = p1;
now, the last pointer alive will delete the allocated memory, and you don't have to worry at all who's deleting what.
And what would happen to pointer p1? In addition, what is the relationship between p1 and p2 essentially?
Their essential relationship is that they are pointing to the same address obtained from dynamic memory allocation after the assignment int* p2 = p1;.
So deleting either of them will free the allocated memory. Setting one of them to nullptr won't affect the other though.
So you're left with a dangling pointer that cannot be deleted safely.
You can delete either p1 or p2. There will be no difference. But you should not delete both. Plus once you deleted one you should not use the other. Programmer is responsible for this. The language itself will not provide any help. There are tons of different ways to write bad code here.
There are several techniques/patterns for handling this. Very often smart pointers are used for this. Look at std::shared_ptr documentation. Do not use outdated auto_ptr.
My favorite pattern is "ownership". This means that one pointer "owns" the allocation while all others just use. This requires certain discipline while programming but once this effort is applied, the resulting code is clear and simple. For example:
class MyClass
{
public: ~MyClass() { for(char *p: myStringsDict) delete p; }
private:
std::unordered_set<char*> myStringsDict;
};
Looking at this class it is clear (although it would be nice to add a proper comment) that it owns a dictionary of strings and these strings are valid as long as the instance of this class exists. These pointers can be used in structures that are owned by this class, they can be passed as parameters to functions, etc. It is clear when they should not be used any more.
In server programming when multiple threads are running, double deleting can be very dangerous and difficult to track down. Because after deleting the first pointer the memory becomes free and may be allocated for some other purpose on a different thread. When the second pointer is being freed it may happen that it is deleting a valid allocation while other piece of code has no idea about this and is continuing to use this piece of memory.
Really good solution for all these problems is garbage collection. When explicit allocations are used, programmer needs to apply additional effort in this or that way.
Let's explore the real estate analogy, where memory plays the role of land and pointers are, not-so-surprisingly, act as addresses.
A pointer variable is a yellow post-it note. You can write a street address on it. A variable allocated from the free store is a patch of land at some address.
int *p = new int;
You ask the city to find a small unused patch of land somewhere and assign the title to yourself. You write down its street address on a yellow note.
*p = 1;
You build a neat little house at that address.
int *q = p;
You make a copy of the yellow note. You forget about it for some time.
delete p;
You demolish the building and give up your rights to the patch of land. The city may allocate it to somebody else. Perhaps someone wants to build another small building there, or maybe lay down railway tracks or set up a shark pool. Note this does nothing whatsoever to any of your yellow notes.
p = nullptr;
You wipe a yellow note clean. Your other yellow note lingers on.
*q = 2;
You find the other yellow note, read a streat address off it and assume that land is yours. Bad move. You proceed to build a neat little house on someone else's land. The new owners couldn't care less (they have no way of knowing). Tomorrow they may demolish your building and put their own in place, or overrun you with a train, or perhaps dump 100000 tons of water and 3 makos on you. That's rather unpleasant! Don't touch what's not yours.
when allocating dynamic memory using new it should be freed by delete, as long as you create p1 using new then free it using delete.
you declare p2 as a pointer pointing at the same memory p1 points to then if you want to free memory call delete on p1 not p2 to be readable however that memory can be freed by calling delete on p1 or p2.
if you call delete on p1 then make p2 to point to null in order not to dereference it by mistake because writing:
delete p1;
*p2 = 1;
will cause an undefined behavior.
Related
lets think we have a code like this :
int * ptr = new int;
int *nptr = ptr
int * ptr2 = new int;
int *nptr2 = 2*nptr+ptr2;
delete ptr;
delete ptr2;
ptr = NULL;
ptr2 = NULL;
So now the nptr and nptr2 is dangling pointer .I know that we can overload new allocating function to trace leaked memory (if we dont use delete command in code ) but dont know how to trace or monitor dangling pointers .
dangling pointers that points to leakded memory?
A pointer that has leaked, by definition is not being pointed by anything. A dangling pointer by definition points to memory that hasn't been leaked. This is a contradiction.
int *nptr2 = 2*nptr+ptr2;
This is ill-formed. Pointers cannot be multiplied by integers, and pointers cannot be added to pointers (I'm assuming the assumption is that result of the ill-formed multiplication is also a pointer). Furthermore, if this pointer arithmetic produced anything other than nptr, nptr+1, nptr2, nptr2+1, then the result would technically be undefined.
but dont know how to trace or monitor dangling pointers .
It's perfectly fine and normal to have dangling pointers. What isn't fine is indirecting through dangling pointers or relying on their value. At least for indirection, you can use an address sanitiser to try catch such bugs. It can find some uses of dangling pointers particularly those to dynamic memory such as the pointers in the question. It's not as good at detecting dangling pointers to automatic variables. On the other hand, compiler can catch simple cases such as returning pointer to local variable.
Alternatively, you can modify your program to use std::shared_ptr so that as long as you still hold a shared pointer, it cannot become dangling. This comes at a small cost of overhead, but it makes it much easier to reason about lifetime correctness.
First of all "dangling pointers that points to leakded memory" makes no sense. I suppose you mistakenly use "leaked memory" for objects that are already destroyed. In your code there is no memory leak. You have a memory leak when you do not have a pointer to some dynamically allocated obejct anymore, as in:
{
int* x = new int;
} // x goes out of scope, no way to delete the int
Further, it is not clear what this line is supposed to do int *nptr2 = 2*nptr+ptr2;. It is not valid C++, hence I am going to ignore it for the rest of the answer. Also the last two lines are not that relevant (maybe for code that comes after the shwon code but not here).
So we are left with:
int * ptr = new int;
int *nptr = ptr
int * ptr2 = new int;
delete ptr;
delete ptr2;
You create two int via new. You delete two int. No memory is leaked. After delete ptr the pointer nptr points to a no longer existing object. nptr is said to be a dangling pointer.
With that out of the way, we can turn to your actual question: How to monitor dangling raw pointers?
You cannot. A raw pointer is rather primitive. It stores an address. And thats all. The pointer is not aware whether there is an object at that adress or not. This is one reason you should not use new and delete and raw pointers to manage memory. Use smart pointers. For example if you share ownership between two std::shared_ptr then the pointee will be kept alive as long as one of the shared pointers is alive. A shared pointer cannot dangle (unless you do something wrong).
I would recommend that you not use raw pointers. If you use smart pointers that then you will never(*) have a dangling pointer. The whole purpose of smart pointers is to ensure that the lifetime of both the pointer and what is pointed to is managed together.
Use std::unique_ptr, std::shared_ptr (and std::weak_ptr if needed).
You can use tools like Valgrind and AddressSanitizer to ensure that you do not use dangling pointers.
(*) never is perhaps too strong, at least make it more difficult.
#include "A.h"
int main (int argc, char*argv[]){
A * p_a1 = new A();
A * p_a2 = p_a1;
delete p_a1;
p_a1 = 0;
delete p_a2 <br>
Could this code where A is some class lead to memory management issues?
My Thoughts:
The first line will create a pointer to A. I am not sure if this will allocate memory for A, too, or will it just assign an address? The second pointer p_a2 points to the exact location. delete p_a1 will delete the allocated memory, which probably didn't have anything p_a1=0, making it null. delete p_a2. We are then deleting the null pointer, which probably won't affect Could this lead to any memory leakage or issues?
Deleting the same object twice is definitely a memory management issue. delete p_a1; does delete the object pointed to by p_a1, then delete p_a2 tries to delete the very same object.
Remember: You are not deleting pointers, but you delete the object they are pointing to.
Raw new is always a code smell and a potential source of bugs. Your code should look like this instead:
#include "A.h"
int main (int argc, char*argv[]){
A a;
}
Frankly, given your question imho one can either only scratch the surface or write a long article to explain important basics. I opted for the first and refer you to a book for more details: The Definitive C++ Book Guide and List
Your problem is that p_a1 and p_a2 are independant pointers which at a time happen to point to the very same object.
After
delete p_a1;
p_a1 = 0;
all is fine from a p_a1 point of view: the object it pointed to has been deleted, and the pointer itself as received a nullptr value, so it is now safe to do delete p_a1 again.
But p_a2 has not been changed and now points to an object that has reached its end of life. So it has become a dangling pointer and dereferencing it or deleting it will invoke UB.
If you want p_a2 to be equivalent to p_a1 you should make it a reference:
A* &p_a2 = p_a1;
Now after p_a1 = 0, p_a2 is a reference to a null pointer and it can safely be deleted.
I'm relatively new to C++ and I want to understand memory management and pointers at the same time.
Let's say I have the code below
int* p1;
int* p2;
int* p3 = new int[some size];
p1 = p3;
std::swap(p1,p2);
How do I properly delete the dynamically allocated memory? Is doing delete[] p3 enough? Should I delete p2 too after that?
There is some fuzzyness in colloquial speech when you do something like this:
delete x;
We say "we delete x". Strictly speaking thats wrong, because what is deleted is the object pointed to by x.
Every object allocated via new/new[] must be destroyed via one call to delete/delete[]. Whether you have two or more pointers to the same object does not change that.
int* p1 = nullptr;
int* p2 = nullptr;
int* p3 = new int[some size]; // p3 points to the array
p1 = p3; // p1 points to the same array
std::swap(p1,p2); // now p1 == nullptr, p2 points to the array
Note that the pointers are uninitialized in your example. Reading their values causes undefined behavior. As this isnt the crux of the question I avoided that by initializing them.
There is one array created via new [] and it is that one array that you have to delete via delete []. You may not delete it twice. So either call delete[] p3; or delete[] p2;, but not both.
PS: Comments already mentioned smart pointers and I also suggest you to read about them. Nowadays you should not use raw owning pointers. An owning pointer is one that you need to call delete on, it "owns" the pointed to object. Raw pointers should only be used to "observe", ie you should never need to worry about calling delete (or delete[]) on a raw pointer. Of course you still need to take care whether the pointed to object is still alive, but that is not specific to dynamic allocation:
int* p;
{
int x = 42;
p = &x; // p points to x;
} // x goes out of scope
// here p is not a valid pointer anymore
To understand what is happening here, it would help to add some debug statements, i.e:
std::cout << p1 << " " << p2 << " " << p3 << "\n";
The trace will result in an output like:
0 0 0x15e7eb0
0x15e7eb0 0 0x15e7eb0
0 0x15e7eb0 0x15e7eb0
(Note that I initialized p1 and p1 to nullptr)
p3 initially points to some memory. After the assignment p1 = p3, p1 now points to the same memory address as p3. When you swap the pointers, now it's p2 that points to the same memory address as p3.
There are a couple of things to note here:
You must pair delete[] with the corresponding new[] (do not call delete with new[] and so forth)
Calling delete on an already deleted object is undefined behavior
Calling delete on a null pointer is perfectly safe
As you can see, dealing with raw pointers and memory allocation can easily lead to pitfalls. It's generally recommended to use smart pointers, or if you have a non-owning pointer, to use abstractions like observer_ptr to clearly indicate the pointer's purpose in the code.
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 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.