How does this work? Pointer to pointer assignment - c++

#include <iostream>
using namespace std;
int main() {
int *p1;
p1 = new int;
int *p2;
p2 = new int;
p2 = p1; // what happens here?
*p1=5;
cout << "pointer 2 is " << *p2 << endl << *p1 << endl; // both give out 5
delete p1; // what happens to p2 ?
cout << "pointer 2 is " << *p2 << endl;
delete p2;
return 0;
}
What happens when I delete the pointer object p1? What is pointer p2 referencing now ? Can some one explain ? Thanks for the help

What is pointer p2 referencing now ?
Nothing. It's dangling. It was pointing to the same thing p1 was pointing to, but you've deleted that.
Consequently, your *p2 is broken, as is your delete p2; these both have undefined behaviour.
You've also leaked the second new int, because p2 used to point to it but stopped doing so when you wrote p2 = p1 (you changed it to point to the first new int instead, like p1 does), and there's no other way to refer to it.

p2 = p1; // what happens here?
You are simply copying the value (pointed memory address) of p1 into p2. This is no different than doing this:
int i1, i2;
i1 = 12345;
i2 = i1;
However, because the value in question in a memory address allocated with new, you now have a memory leak, as you have lost your only pointer to the 2nd allocated int that p2 was previously pointing at. Now p1 and p2 are both pointing at the 1st int in memory.
cout << "pointer 2 is " << *p2 << endl << *p1 << endl; // both give out 5
Yes, because p1 and p2 are pointing at the same memory address.
delete p1; // what happens to p2 ?
Nothing happens to p2 here, it is still pointing at the same memory address it was before. p1 and p2 are independent variables, so a change to one does not affect the other. But, the delete has deallocated the 1st int that was stored at the memory address being pointed at by p1 and p2, so now they are both dangling pointers to invalid memory. Since you don't use p1 after this, that is ok for p1, but for p2 the next statements:
cout << "pointer 2 is " << *p2 << endl;
delete p2;
Will cause Undefined Behavior, because you are accessing invalid memory via the dangling p2. The read may succeed in returning stale data that is still present at the memory address, or it may return garbage, or it may crash. The delete will almost certainly crash, since the memory has already been freed earlier, but that is not guaranteed either. Undefined Behaivor is just that - undefined - so literally anything could happen.

Related

I am getting a issue in copying a pointer to another pointer in c++

I am getting segmentation fault in first code but the second code is running fine, don't know how?
How can I copy a pointer and save it to another pointer?
#include <iostream>
using namespace std;
int main() {
int *p;
int *p1;
*p1=7;
p=p1;
cout<<*p<<" "<<p;
return 0;
}
#include <iostream>
using namespace std;
int main() {
int *p1;
*p1=7;
int *p=p1;
cout<<*p<<" "<<p;
return 0;
}
//7 0x7ffeea73db70
Both cases invoke undefined behaviour, in both cases you make use of uninitialized pointer p1, the fact that the second case "works" for you is a matter of sheer luck, as you can see here.
For your code to be valid you need to make it point to a valid memory address either by allocating memory manually:
int *p1 = new int; //raw pointer, (better to use smart pointers* but let's not get ahead of ourselves).
Or by assigning it the address of a valid int variable:
int i = 5;
int *p1 = &i;
How can I copy a pointer and save it to another pointer?
A pointer is essentially a variable like any other, you can copy it like you do a normal primitive variable, in fact you do just that when you do p = p1, these are two different pointers that will now contain the same value, the address of the variable they point to.
This code exemplifies this
#include <iostream>
using std::cout;
using std::endl;
int main() {
int *p1 = new int;
*p1 = 7;
int *p = p1;
cout<< "Value stored in the address p points to: " << *p << endl
<< "Value stored in the address p1 points to: " << *p1 << endl
<< "Address where p points to: " << p
<< " " << endl << "Address where p1 points to: "<< p1
<< endl << "Address of p: " << &p << endl << "Address of p1: "<< &p1;
return 0;
}
The output:
Value stored in the address p points to: 7
Value stored in the address p1 points to: 7
Address where p points to: 0x804150
Address where p1 points to: 0x804150
Address of p: 0x7ffc9447e220
Address of p1: 0x7ffc9447e228
*What is a smart pointer and when should I use one?
When you dereference an int* pointer, you promise that there is an int object at that address. C++ believes you, often without questioning. But you never wrote int a; p1=&a; or any other code that made sure p1 points to an actual int.
In fact, p1 isn't even a null pointer. The only thing you can do with p1 is to assign it a legal value. That is to say, it must appear at the left-hand side of an assignment first. It can't be used on the right hand side in int* p = p1;

Not able to understand the notations : * and ** with pointers

I have a problem with the pointers. I know what this does:
*name
I understand that this is a pointer.
I've been searching but I do neither understand what this one does nor I've found helpful information
**name
The context is int **name, not multiplication
Could someone help me?
NOTE: Without the proper context, the usage of *name and **name is ambiguous. it may portrait (a). dereference operator (b) multiplication operator
Considering you're talking about a scenario like
char * name;
char **name;
in the code,
*name
name is a pointer to a char.
**name
name is a pointer, to the pointer to a char.
Please don't get confused with "double-pointer", which is sometimes used to denote pointer to a pointer but actually supposed to mean a pointer to a double data type variable.
A visual below
As above, we can say
char value = `c`;
char *p2 = &value; // &value is 8000, so p2 == 8000, &p2 == 5000
char **p1 = &p2; // &p2 == 5000, p1 == 5000
So, p1 here, is a pointer-to-pointer. Hope this make things clear now.
It's actually very simple, consider this:
int a; // a is an int
int* b; // b is a pointer to an int
int** c; // c is a pointer to a pointer to an int
If you see every level as just another variable type (so, see *int as a type), it's easier to understand.
Another example:
typedef int* IntPointer;
IntPointer a; // a is an IntPointer
IntPointer* b; // b is a pointer to an IntPointer!
Hope that helps!
pointer stores address of variable, pointer to pointer stores address of another pointer.
int var
int *ptr;
int **ptr2;
ptr = &var;
ptr2 = &ptr;
cout << "var : " << var;
cout << "*ptr : " << *ptr;
cout << "**ptr2 : " << **ptr2;
You can look here
int a = 5;// a is int, a = 5.
int *p1 = &a; // p1 is pointer, p1 point to physical address of a;
int **p2 = &p1; // p2 is pointer of pointer, p2 point to physical adress of p1;
cout<< "a = "<<a << " *p1 = "<<*p1<<" *(*p2) = " << *(*p2)<<endl;
**name in this case. Would be a pointer to a pointer.

C++ How to properly copy the value of a pointer

So I'm having a bit of an issue, and need help with this beginner question.
I've changed my example so that it makes sense. I should not have posted one while sleep deprived.
I'm trying to copy a pointer (lets call it p1) in order to create a second pointer (lets call it p2).
When p1 changes the object it is pointing at, I don't want p2 to change along with it, which is what appears to be happening in my program.
Essentially, here is the issue I'm having....
#include <string>
#include <iostream>
int main(){
std::cout << "Pointer Test\n\n";
int num1, num2;
int * p1, * p2;
num1 = 5;
num2 = 10;
p1 = &num1;
p2 = p1;
std::cout << "P1 is pointing at value " << *p1 << " (should be 5)\n";
std::cout << "P2 is pointing at value " << *p2 << " (should be 5)\n\n";
*p1 = num2; //Even though the value of P1 is changing, I don't want the value of P2 to change. I want it to stay on num1
std::cout << "P1 is pointing at value " << *p1 << " (should be 10)\n";
std::cout << "P2 is pointing at value " << *p2 << " (I want this to be 5, not 10)\n";
return 0;
}
/*
Assignments I've tried to make this work...
p2 = p1; //didn't work - *p2 changes when *p1 does, which I am trying to avoid
*p2 = *p1; //didn't work - caused segfault
*p2 = p1; //didn't work - can't convert int to *int, so won't compile
p2 = &(*p1); //didn't work - gave same result as p2 = p1
*/
Any enlightenment on this matter would be greatly appreciated.
I think you have a misunderstanding of what is going on. The statement *p1 = num2; is not changing the value of p1, it is changing the value of whatever p1 points to. Since both p1 and p2 point to the same variable when you change its value through one pointer you will see the same value when you dereference either pointer. What you want to do is have p1 point to num2, not take the value of num2 and store it in whatever p1 points to.
Change
*p1 = num2;
to
p1 = &num2;
Consider the following code:
int a = 5, b = 10, *foo, *bar;
foo = &a; // foo now points at the address of A
bar = foo; // bar now points at the address at which foo is pointing
foo = &b; // foo now points at the address of B
cout << *foo; // prints 10
cout << *bar; // prints 5
Thats the behaviour you want to achieve if Im not mistaken.
Your code is nonsensical however. IF I'm not wrong, your mistake is that you create a second pointer which points at the address of the first pointer instead of pointing at the address from the first pointer.
Your first code makes no sense. If testObj isn´t a typedef to a pointer,
the * in the first p1 assignment is wrong (it should be &), and the second p1 assignment is wrong too, because you can´t assign a temporary object to a pointer, (only addresses to variables or from new).
And always remember to assign an address to a pointer p before using *p
If you want to copy pointers, the copy will point to the same thing as the original one and p2 = p1; is correct. If you want to copy objects, the pointer thing has nothing to do with it, and how the object is copied should be defined in a copy constructor and operator=.
Depending on the class, memcpy can work or not, don´t rely on it for such cases.
Nonsensical code aside
When p1 changes the object it is pointing at, I don't want p2 to change along with it
If p1 and p2 point to the same object, changing the object p1 points to will change the (same) object p2 points to, period. You'll have to use a different mechanism than raw pointers to avoid that behaviour. Like making copies of the object pointed to instead of copying the pointer.
Also
Do I have to use memcpy? Or is there another way?
Since this is C++, I'd avoid memcpy.
Defining a copy constructor or assignment operator is a better way of copying objects.
There is no type like obj *. The "*" binds tighter to "p1". So you need to change the decl from
obj * p1, p2;
To
obj *p1, *p2;

Operator precedence and pointer arithmetic

Given the following code:
void Allocate(int *p)
{
p = new int;
*p++ = 2;
}
int main()
{
int i = 10;
Allocate(&i);
std::cout << i << std::endl;
}
I'm a bit confised about the meaning of:
*p++ = 2;
The output is 10 and my reasoning as to why this is the case is that *p++ is a temporary therefore any assignment to it is lost at the end of the scope of Allocate(int *p).
Is this the case?
Thanks in adv!
On input to Allocate, p points to the variable i in the main
function.
The address of this variable then lost and replaced by the
new int.
The value of this int (which is uninitialized and so could
start as anything) is set to 2.
The p pointer is incremented.
The Allocate function returns at this point, leaking the int that was
allocated.
The value of i in the main function is unchanged,
because Allocate did not modify it.
when you pass the the address of i into Allocate, another (temp) pointer is created that points to i's address (i.e. passing by pointer). then that temp pointer is pointed to a new location (via new int). thus the value of i is left alone.
p = new int;
You're assigning p new memory to point to instead of what it was pointing to before. You then change this newly allocated memory and it's lost forever when the function ends, causing a memory leak. If you remove the allocation line, it should cause an output of 2. The ++ does nothing in this case. It just increments the pointer and returns the old value to dereference.
As soon as you enter Allocate, you assign p to point to a new block of memory, so it no longer points to i. Then you modify that new block of memory (which is then leaked when the method returns.) i is unaffected because you've moved that pointer before you set the pointed-to memory cell.
void Allocate(int **p)
{
*p = new int;
**p = 2;
}
int main()
{
int j = 10;
int *i = &j;
std::cout << i << std::endl;
Allocate(&i);
std::cout << i << std::endl;
}
Output is :
10
2
You need a pointer to pointer to change the address of the location being pointed to.

Asserting that both pointers point to NULL is not happening after delete()

Given this little piece of code :
#include <iostream>
#include <assert.h>
using namespace std;
struct Foo
{
// something
};
int main()
{
Foo *p1 = new Foo;
Foo * p2 = p1;
assert(NULL != p1);
delete p1;
p1 = NULL;
assert(NULL != p2);
delete p2;
cout << "everything is cool!" << endl;
return 0;
}
When I delete p1 , the second assert (assert(NULL != p2);) is not failing , why ?
The output : everything is cool!
Then why the assert of p2 is not failing ?
When I delete p1 , the second assert (assert(NULL != p2);) is not
failing , why ?
Deleting p1 or assigning to it has no effect on p2 itself. After you delete p1, p2 still points to that address, i.e. to a defunct object. It becomes a so-called dangling pointer. Of course, accessing it or deleting it (which you're doing) is undefined behavior.
Watch the stars, in particular.
int i;
int *p1 = &i;
assert(p1 != NULL);
int *p2 = p1;
assert(p2 != NULL);
*p1 = 10;
assert(i == 10);
assert(*p2 == 10);
p1 = NULL; // does not affect the object p1 was pointing at
assert(i == 10);
assert(*p2 == 10);
assert(p2 != NULL); // (which we already know, if the previous assert didn't crash)
You're right to suspect that everything is not cool. The program invokes the delete operator twice on the same object (a "double free" error), which will tend to corrupt the heap. If the program continued, you would see undefined behavior at some point. Having undefined behavior rather defeats the point of writing a computer program. If you want to see errors like this immediately and unambiguously, run it under valgrind's memcheck or equivalent.
One of the biggest and most confusing-to-beginners misnomer in C++ is the term "deleting a pointer". This has undoubtedly originated from the fact that a delete expression takes a pointer as its argument:
T * p = new T; // #1
delete p; // #2
However, what's really going on is that line #1 creates a new, dynamic, unnamed object. Think about this again: There is no variable whose value is the object create in line #1. The object is really out of reach, as indeed it does not live in any scope. All we have is a pointer to it.
To end the lifetime of a dynamic variable, we have to use a delete expression. But since we already know that we can only ever really have a pointer the object, not the object itself*, the expression con­veni­ent­ly accepts a pointer to the object we're deleting.
So really we should say that in line #2 "we are deleting the object *p by giving a pointer to it to the delete expression" (namely &*p == p).
The pointer itself is entirely unaffected by the delete call.
*) Yes, we could also have a reference variable, like T & r = *new T;, but that would be insane.
delete p; doesn't affect p. It destroys the object that p points to and frees its memory. p still has the value that it had before.