C++ Dangling Pointers and Memory Leaks - c++

I'm having a hard time understanding how to tell between dangling pointers and memory leaks. I have a few questions on a recent assignment that are puzzling me, and after reading into it, I am still puzzled. I don't want someone to do my homework for me, I want to be able to understand why something is what it is, if that makes sense.
So, the homework:
Given the declarations:
int *ptrA, *ptrB;
Tell whether each code segment below results in a memory leak, a dangling pointer, or neither. Draw pictures to help.
I'm guessing that this is fine, as ptrA is already pointing to something in memory, so this one is neither a dangling pointer or a memory leak.
ptrA = new int;
ptrB = new int;
*ptrA = 345;
ptrB = ptrA;
I'm guessing that this is a dangling pointer because 345 was deallocated from memory, so ptrB points to nothing.
ptrA = new int;
*ptrA = 345;
ptrB = ptrA;
delete ptrA;
This is where I'm complete lost. Does the last line mean that the pointer is pointing to another pointer? Not sure what the implications of this would be.
ptrA = new int;
ptrB = new int;
*ptrA = 345;
*ptrB = *ptrA;
Like the previous question, I'm not sure what pointing to a pointer means, or if I even understand what this is achieving.
ptrA = new int;
ptrB = new int;
*ptrA = 345;
ptrB = new int;
*ptrB = *ptrA;
I know this is a dangling pointer, but I don't know why. Is it because the pointer is pointing to a local variable that went out of scope when the function finished?
ptrA = LocationOfAge();
where function LocationOfAge is defined as:
int *LocationOfAge() {
int age = 21;
return &age;
}
Thanks for anyone willing to help.

The rules of the game:
For every new Type draw a box. Put a question in the box (you don't know what is in there).
For every delete p cross out the box pointed to by p.
For every a = b (where there are no stars) draw a line from variable a to a box b.
For every *x = y write y inside the box pointed at by x.
For every *x = *y read the content of the box y and put a copy in x
The result:
When you have a box with no variables pointing at it you have a leak.
If you have a pointer that does not point at a box (or a crossed out box) you have a dangling pointer.
The first problem:
ptrA = new int;
ptrB = new int;
*ptrA = 345;
ptrB = ptrA;
Lets do this line by line:
ptrA = new int;
// Part 1 has a new so draw a box
*********
* ? *
*********
// Part 2 assignment to variable add a line
ptrA -------> *********
* ? *
*********
ptrB = new int;
// Part 3 has a new so draw another box
ptrA -------> *********
* ? *
*********
*********
* ? *
*********
// Part 4 assignment to variable add a line
ptrA -------> *********
* ? *
*********
ptrB -------> *********
* ? *
*********
*ptrA = 345;
ptrA -------> *********
* 345 *
*********
ptrB -------> *********
* ? *
*********
ptrB = ptrA;
ptrA -------> *********
| * 345 *
| *********
|
ptrB ---- *********
* ? *
*********
Seems like you have a leaked box. i.e. There is a box with no variable pointing at it.

I'm guessing that this is fine, as ptrA is already pointing to something in memory, so this one is neither a dangling pointer or a memory leak.
Yeah but now ptrB points to it too, and you have no way of freeing the thing that ptrB pointed to before.
So that's a leak.
I'm guessing that this is a dangling pointer because 345 was deallocated from memory, so ptrB points to nothing.
Correct.
Does the last line mean that the pointer is pointing to another pointer?
No, it gives <the thing that ptrB points to> the value of <the thing that ptrA points to>. No changes to the pointers involved, only int assignment.
Like the previous question, I'm not sure what pointing to a pointer means, or if I even understand what this is achieving.
The second new int is leaked, because the thing that used to point to it (ptrB) now points to a third new int and the former can no longer be freed.
I know this is a dangling pointer, but I don't know why. Is it because the pointer is pointing to a local variable that went out of scope when the function finished?
Yes.

To prevent making all homework, your first assumption is wrong.
1. ptrA = new int;
2. ptrB = new int;
3. *ptrA = 345;
4. ptrB = ptrA;
In line 1, ptrA creates a new integer (bytes are allocated), in line 2 ptrB allocates bytes. Than in 3, the memory allocated in 1 is filled, which is OK.
However, in line 4, ptrB is overwritten with the address of 3, this means the original addres of ptrB is not reachable anymore. And thus there is a memory leak, because the bytes allocated for the integer PtrB by line 2 can never be accessed anymore, since there is no pointer pointing to it.
It's much easier if you write a drawing, by using arrows for pointers and a box with either a ? for a declaration and a specific value when filled in. So it would look like:
1. ptrA -> [ ? ]
2. ptrA -> [ ? ], ptrB -> [ ? ]
3. ptrA -> [ 345 ], ptrB -> [ ? ]
4. ptrA -> [ 345 ] <- ptrB, [ ? ]
As you can see, the last box [ ? ] does not have any pointer pointing to it.

Let's take one question at a time.
ptrA = new int;
ptrB = new int;
*ptrA = 345;
ptrB = ptrA;
Here, it is a memory leak. Why? Because there is no delete first of all. Secondly, when you do ptrB = ptrA;, there is practically no way to call delete for the object that was pointed to by ptrB earlier.
ptrA = new int;
*ptrA = 345;
ptrB = ptrA;
delete ptrA;
This is an example of dangling pointer. Once delete is called on ptrA, the object pointed to by ptrA gets deallocated. So, ptrB points to a deallocated location whose behaviour is undefined. So, Dangling pointer!
ptrA = new int;
ptrB = new int;
*ptrA = 345;
*ptrB = *ptrA;
Here, there is memory leak simply because we are not calling delete. What we are doing is that we are creating two objects which are pointed by ptrA and ptrB respectively and both objects have value of 345. They still hold space in the heap. But how come both have the value of 345? Simple.
When you did *ptrA = 345;, it meant that the value of the object pointed to by ptrA should be set to 345.
When you did *ptrB = *ptrA;, it meant that the value of the object pointed by ptrB should be assigned with the value of the object pointed by ptrA.
This is the simple functioning of dereferencing operator.
ptrA = new int;
ptrB = new int;
*ptrA = 345;
ptrB = new int;
*ptrB = *ptrA;
This is similar to first one. In line 2, ptrB pointed to a dynamically allocated object. After execution of Line 4, ptrB points to entirely new object. So, there is no way to deallocate the object whose memory was allocated at line 2. So, Memory Leak!
int *LocationOfAge() {
int age = 21;
return &age;
}
Here, age is a local variable which will die once the function ends. So, any pointer to that local variable leads to undefined behaviour. So, Dangling Pointer!

Related

About delete in C++

I'm freshman in c++.
What's the difference between "delete a" and "delete b" ? Thanks a lot!
int* a = NULL ;
int* b = new int(10) ;
a = b;
delete a;//does the space of b free?
delete b;
ps:my bad!i dont mean delete a,b at same time,it's actually two ways of delete memery which i wanna ask.
Another question!
How to release the int allocated by the expression new int(10) in case 2?
//case 1: right
int *a= new int(10);
delete a;
//case 2:
int b = *new int(10); // how to release the int?
You called a single new, you need to a call a single delete. After a = b; you can delete either one. But you must delete only one. Deleting through either pointer will have the same effect. After the delete call, both variables will become invalid, pointing to freed memory.

What happens to values on the stack that get placed in array on the Heap

I want to know if I create an array on the Heap in C++ and I assign data from the stack to the Array, what exactly happens? Is the data copied onto the heap?
code fragment:
int a = 1;
int b = 2;
int *c = new int(3);
int *arr = new int[3];
arr[0] = a;
arr[1] = b;
arr[2] = *c;
int a = 3;
a has the value 3.
the memory address of a is 0x345A or something like it.
a is on the stack.
int *p = &a;
pointer p is assigned the address of a. The memory address of p is 0x123B or something like it. That memory address holds the value 0x345A pointing to the location where the value 3 is stored. Pointer p is on the stack.
You'd get 3 if you print a and *p since they are getting their value from the same memory location.
You'd get 0x345A if you print &a and p since a's address is the value p holds.
You'd get 0x123B if you print &p since that is the memory location for pointer p.
Assuming *c points to an integer on the heap, you could store the value of c (which is the memory address of the integer on heap) in an array.
int *arr = new int[3];
...
arr[2] = c;
What you do NOT want to do is:
int foo = 10;
arr[2] = &foo;
Now, your array is pointing to a memory location that that is on the stack. Will work OK as long as you are in that function, but will be pointing at garbage once you exit the function and stack is reclaimed.

Pointers with runtime allocation

I don't get that why reassigning a value to *p shows error. We've deleted it's resources, created at run time.
int a = 7, b = 8;
int *p = new int;
*p = a;
cout<<*p<<" "<<p<<endl;
delete p;
cout<<*p<<" "<<p;
*p = &b; // error
cout<<"\n"<<*p<<" "<<p;
The behaviour on dereferencing p after you've called delete p; is undefined. Don't do that. That's the easy bit. Now for the harder bit: the behaviour on reading the value of p (let alone dereferencing it) following a call to delete is undefined too! So don't do that either. (Informally you put the pointer back to an uninitialised state.)
*p = &b; is a typo. You need p = &b; to assign the pointer p to the address of b. If you fix that typo, you are free to read the value of p and dereference it once again.
The problem besides deleting the pointer and not giving it a new address is currently you are trying to assign the value of the p pointer to a memory address of an int.

Using "new" multiple times on the same pointer

What happens when I do something like
int * ptr = new int;
*ptr = 5;
// ... do some stuff here
ptr = new int;
// ... reuse ptr to do some other stuff
as opposed to
int * ptr1 = new int;
*ptr1 = 5;
// ... do some stuff here
delete ptr1;
int * ptr2 = new int;
// ... use ptr2 now
????
Does the same thing happen at the hardware level? In other words, in the first case, does ptr = new int; move on from its previous pointer/value pair, and what happens to those old values? Do they get replaced, do they just float around somewhere, etc.?
Your int *ptr is just a variable that stores an address, nothing more.
After your first int * ptr = new int;, it contains the address to a dynamically allocated integer. After your second int * ptr = new int;, it contains the address to another dynamically allocated integer.
What happens then is nothing special, the only thing is that you didn't call delete so the memory allocated for the first integer will never be freed. There's nothing to keep track of it, its address isn't stored anywhere, and so it will keep being useless allocated space until the program ends.
In the first example, the pointer is overwritten, but the object it pointed to still exists and is "floating around" somewhere. This causes memory leaking.
If this happens in a frequently used function or in a loop, you could easily exhaust your memory, storing values that you can't nor won't access any more.
Leaking is in fact a very common error. A good practice is to avoid it by using smart pointers such as shared_ptr. These keep track of a usage count, and free the object automatically if it's no longer used. For example:
shared_ptr<int> ptr = make_shared<int>(); // allocate an int
*ptr = 5;
// ... do some stuff here
ptr = make_shared<int>(); // the old object is no longer used so deleted automatically
// ... reuse ptr to do some other stuff

Placement new for block of pointers

i am trying to allocate pointers of the first order one by one at memory.
Pointer of the second order must walk through this queue and handle to objects, created on that pointers.
Placement new works fine when i allocate the queue of objects(not pointers to them), but when i am trying the same with pointers the trouble happens.
int* p;
p = new int(1);
printf("%p - %d\n", p, *p); // address of int and its value
delete p;
First object is created and deleted to initialize pointer with some address, next objects will be created in cycle
p = new(p) int(2); // (p) - memory will be allocated at address
// on which p points
printf("%p - %d\n", p, *p); // address of int and its value
delete p;
p++;
p = new(p) int(3); // (p) - memory will be allocated at address
// on which p points
printf("%p - %d\n", p, *p); // address of int and its value
delete p;
Output:
01C1FFD0 - 1
01C1FFD0 - 2
01C1FFD4 - 3;
int** pp;
pp = new int*;
printf("%p\n", pp); // address of int*
*pp = new int(1);
printf("%p - %d\n", *pp, **pp); // address of int and its value
delete *pp;
delete pp;
pp = new(pp) int*;
printf("%p\n", pp); // address of int*
*pp = new int(2);
printf("%p - %d\n", *pp, **pp); // address of int and its value
delete *pp;
delete pp;
pp++;
pp = new(pp) int*;
printf("%p\n", pp); // address of int*
*pp = new int(3);
printf("%p - %d\n", *pp, **pp); // address of int and its value
delete *pp;
delete pp;
If int is not created by *pp then if pp is incremented it is not real to delete pp later,
if int is created by *pp then there is something strange with addresses and second value.
Output:
01C1FFD0
01C1FFE0 - 1
01C1FFD0
01C1FFD0 - 29491152
01C1FFD4
01C1FFD0 - 3
I would be very grateful for advice how to organize this queue correct.
p = new(p) int(2); // (p) - memory will be allocated at address
// on which p points
This is where you're wrong for the first time. new(p) T does not allocate any memory. Rather than that, it just creates a T at address p, assuming that p points to some memory where a T can be constructed. Also, since there is no memory allocated, you cannot just pass such pointers to delete, as this will attempt to release the not allocated storage. Rather than that, you need to manually invoke the destructor and dispose of the memory depending on however you acquired it.
Placement new is a rather advanced concept that you very likely do not need at this time. In fact, even "simple" manual memory/object lifetime management is something you probably should not be bothering yourself with at this time of your learning. What book are you learning C++ from? Have you seen this book list?
FYI: I haven't looked at your code below that line.