Understanding Delete in c++ [duplicate] - c++

This question already has answers here:
Using pointer after free()
(6 answers)
Can a local variable's memory be accessed outside its scope?
(20 answers)
Closed 9 months ago.
I created a pointer code in which I played with pointers a little bit but when I tried to delete my pointer variable it still showed me the value which was stored in a pointer variable, after deletion I can still be able to use that pointer variable but I deleted that pointer variable so how can I reuse that after deleting? I don't get that.
Code:
#include<iostream>
int main()
{
using namespace std;
int *m = new int;
int *ab = new int;
cout << "Enter value of m: ";
cin >> *m;
cout << "Address of pointer m: " << m <<endl;
cout << "Content of pointer m: " << *m << endl;
ab = m;
cout << "Address of pointer ab: " << ab <<endl;
cout << "Content of pointer ab: " << *ab << endl;
*m = 34;
cout << "Address of pointer ab: " << ab <<endl;
cout << "Content of pointer ab: " << *ab << endl;
*ab = 7;
cout << "Address of pointer m: " << m <<endl;
cout << "Content of pointer m: " << *m << endl;
delete ab;
delete m;
cout << *m + 1 << endl; //this is giving me result of *m + 1 which is not ok cuz I deleted pointer variable on above line.
return 0;
}

Related

question about modifying a pointer using another pointer in a function

I have a question about the following code. I am not sure why the address stored in yAdd doesn't get updated to the same address stored in the variable x inside the addfun() function in the code below? what is wrong with my thinking?
#include <iostream>
using namespace std;
void fun(int *x) {
*x = 55;
}
void addfun(int **x) {
*x = new int[3];
cout << x << endl; // x stores the address of int[0]
// say it is 0x7ffc32e646a0
cout << &x << endl;
}
int main()
{
int y = 99;
int *yAdd = &y;
cout << y << endl;
fun(yAdd);
cout << y << endl;
cout << yAdd << endl; // original address stored in yAdd
cout << "address of y is " << &y << endl;
addfun(&yAdd); // so I update the address stored in yAdd to be the same address
// as stored inside the x in the addfun function
cout << yAdd << endl; // but how come when printing this, yAdd doesn't
// show 0x7ffc32e646a0, but something else?
return 0;
}
addfun(&yAdd);
This is passing the address of yAdd to this function, as a parameter.
yAdd is a pointer. The pointer is an address of some other object in your program. It doesn't matter what that object is, yAdd is its pointer, and whatever yAdd itself, its address gets passed.
cout << yAdd << endl;
This shows the value of yAdd. Whatever this pointer is, its value is shown. And the address of this object, of yAdd, is something completely different.
void addfun(int **x)
x is a parameter to this function. x is a variable, that has nothing to do, whatsoever, with any other variable in your program. As such, it will have its own memory address, different than the memory address of everything else in your program (at least while it exists).
cout << &x << endl;
And this shows x's address. It is not showing the value of yAdd. It is not showing yAdds address, either. It is showing the address of x, a parameter to this function.
All of these are separate, distinct, objects and values in your program.
I changed the code to print out some more and label it better:
#include <iostream>
using namespace std;
void fun(int *x) {
*x = 55;
}
void addfun(int **x) {
cout << endl << "addfun()" << endl;
cout << "x = " << x << endl;
cout << "*x = " << *x << endl;
cout << "new int[3]" << endl;
*x = new int[3];
cout << "x = " << x << endl;
cout << "*x = " << *x << endl;
cout << "addfun() done" << endl << endl;
}
int main()
{
int y = 99;
int *yAdd = &y;
cout << y << endl;
fun(yAdd);
cout << y << endl;
cout << "&yAdd = " << &yAdd << endl;
cout << "yAdd = " << yAdd << endl;
cout << "*yAdd = " << *yAdd << endl;
cout << "address of y is " << &y << endl;
addfun(&yAdd); // so I update the address stored in yAdd to be the same address
// as stored inside the x in the addfun function
cout << "&yAdd = " << &yAdd << endl;
cout << "yAdd = " << yAdd << endl;
cout << "*yAdd = " << *yAdd << endl;
return 0;
}
This produces for example the following output:
99
55
&yAdd = 0x7ffc9e47fe58
yAdd = 0x7ffc9e47fe54
*yAdd = 55
address of y is 0x7ffc9e47fe54
addfun()
x = 0x7ffc9e47fe58
*x = 0x7ffc9e47fe54
new int[3]
x = 0x7ffc9e47fe58
*x = 0x564ab462d2c0
addfun() done
&yAdd = 0x7ffc9e47fe58
yAdd = 0x564ab462d2c0
*yAdd = 0
As you can see when you enter addfun the value of x is the address of yAdd which points to y. Then you allocate the int[3] and assign the result to *x. That is you store the address of int[3] into where x points to, namely yAdd. The value of x is not changed.
After the call to addfun you can see that the address of yAdd is still the same as and the same as x was but where yAdd points to has now been changed to int[3].
I think the bit where you got confused is *x = .... That changes the things x points at and not x itself.
Within the function addfun
void addfun(int **x) {
*x = new int[3];
cout << x << endl; // x stores the address of int[0]
// say it is 0x7ffc32e646a0
cout << &x << endl;
}
the statement
cout << x << endl; // x stores the address of int[0]
// say it is 0x7ffc32e646a0
prints the address of the original pointer yAdd passed to the function
addfun(&yAdd);
In main this statement
cout << yAdd << endl;
outputs the value assigned to the pointer within the function addfun in this statement
*x = new int[3];
that is the address of the dynamically allocated memory.
The assigned value to the pointer yAdd and the address of the pointer itself are two different values.

What happens when I use *(int*)&x to assign to a constant value x? [duplicate]

This question already has answers here:
Modifying a const int in C++ [duplicate]
(2 answers)
Closed 5 years ago.
I have tried the following codes:
#include <iostream>
using namespace std;
struct MyClass {
const int x;
};
int main() {
MyClass c = {3};
const int *p = &c.x;
cout << "x = " << c.x << endl;
cout << "&x = " << &c.x << endl;
cout << "p = " << p << endl;
cout << "*p = " << *p << endl;
cout << "*(&x) = " << *(&c.x) << endl;
cout << endl;
*(int*)&c.x = 4;
cout << "x = " << c.x << endl;
cout << "&x = " << &c.x << endl;
cout << "p = " << p << endl;
cout << "*p = " << *p << endl;
cout << "*(&x) = " << *(&c.x) << endl;
cout << (p == &c.x) << endl;
cout << (*p == *(&c.x)) << endl;
return 0;
}
Then I get the following answer:
x = 3
&x = 0x61fe98
p = 0x61fe98
*p = 3
*(&x) = 3
x = 4
&x = 0x61fe98
p = 0x61fe98
*p = 4
*(&x) = 4
1
1
It seems that I have successfully change the value of constant integer x. But when I directly declare x in main() instead of in a class, I get the totally different answer.
#include <iostream>
using namespace std;
int main() {
const int x = 3;
const int *p = &x;
cout << "x = " << x << endl;
cout << "&x = " << &x << endl;
cout << "p = " << p << endl;
cout << "*p = " << *p << endl;
cout << "*(&x) = " << *(&x) << endl;
cout << endl;
*(int*)&x = 4;
cout << "x = " << x << endl;
cout << "&x = " << &x << endl;
cout << "p = " << p << endl;
cout << "*p = " << *p << endl;
cout << "*(&x) = " << *(&x) << endl;
cout << endl;
cout << (p == &x) << endl;
cout << (*p == *(&x)) << endl;
return 0;
}
The result is
x = 3
&x = 0x61fe98
p = 0x61fe98
*p = 3
*(&x) = 3
x = 3
&x = 0x61fe98
p = 0x61fe98
*p = 4
*(&x) = 3
1
0
That is really strange that (p == &x) is true but (*p == *(&x)) is false!!! I don't know what's going on in the second codes.
What you're doing is undefined behaviour, so anything can happen. The C++ standard says:
Except that any class member declared mutable (10.1.1) can be modified, any attempt to modify a const object during its lifetime (6.8) results in undefined behavior.
And:
[Note: Depending on the type of the object, a write operation through the pointer, lvalue or pointer to data member resulting from a const_cast that casts away a const-qualifier may produce undefined
behavior (10.1.7.1). — end note]
So you can cast away the "const" to get int* but attempting to actually modify the variable through that pointer is undefined.
The reason you can cast away the const is that it might not actually point to a constant:
int i = 0;
const int* p = &i;
*(int*)p = 1; // OK, because p points to a non-constant
const int j = 0;
const int* q = &j;
*(int*)q = 1; // NOT OK, because q points to a constant
In your second example the compiler is making assumptions when optimizing, based on the fact it knows that a constant value will not change, so it doesn't bother testing its value. The assumption is correct because a correct program can never change the value of a constant. Your program is not correct, but that means the compiler isn't required to give a sensible result.

Redefining a corrupted reference

class A
{
};
int main()
{
A *a= new A(); // variable "a" must be pointer, I can't edit this line
A& b = *a; //b must be a reference
delete a; //deletion
a= new A(); //re-definition
//b is now corrupted.
}
In a piece of code that I have to work with, a pointer to an object of class A is created and a reference to this pointer too.
For some reasons, I have to delete the pointer and re-defined it. How can I get b to work again ?
You can do this, subject to some constraints:
A* a = new A(); // variable "a" must be pointer, I can't edit this line
A& b = *a; // b must be a reference
a->~A(); // destroy first object
new (a) A(); // create second, new object in its place
delete a; // destroy second object and release memory
The constraints are if A contains non-static const data members, you cannot use b after the reconstruction.
(Starting with C++17, you can reuse a reconstructed object even if it has const members by using some extra acrobatics: A& b2 = *std::launder(a); But you still cannot reuse b as is.)
in your code you are not using a reference to a pointer, to do so:
#include <iostream>
#include <string>
using namespace std;
int main()
{
int* ptrA = new int(77);
int*& rPtrA = ptrA; // this a reference to a pointer
cout << "ptrA: " << ptrA << endl;
cout << "*ptrA: " << *ptrA << endl;
cout << "rPtrA: " << rPtrA << endl;
cout << "*rPtrA: " << *rPtrA << endl;
delete ptrA;
ptrA = NULL;
cout << "ptrA: " << ptrA << endl;
// cout << "*ptrA: " << *ptrA << endl; // cause runtme error
cout << "rPtrA: " << rPtrA << endl;
// cout << "*rPtrA: " << *rPtrA << endl;// cause runtme error
ptrA = new int(100);
cout << "ptrA: " << ptrA << endl;
cout << "*ptrA: " << *ptrA << endl;
cout << "rPtrA: " << rPtrA << endl;
cout << "*rPtrA: " << *rPtrA << endl;
delete rPtrA; // delete pointer through its reference
rPtrA = NULL;
cout << "ptrA: " << ptrA << endl;
// cout << "*ptrA: " << *ptrA << endl; // runtime error
cout << "rPtrA: " << rPtrA << endl;
// cout << "*rPtrA: " << *rPtrA << endl; // runtime error
return 0;
}
&* is used for reference to pointer not just &.
a reference is a just another pseudonym to a variable so whatever the variable changes the reference changes also.
a reference to a pointer REFERS to the POINTER'S ADDRESS not the address the pointer stores (value of pointer).
in your code you used a reference to the value(what pointer stores not the pointer itself) the pointer points to

Explain C++ pointer initialization

int value = 3;
int *pValue1 = &value;
int *pValue2(pValue1);
cout << (*pValue1) << " " << (*pValue2);
In the above code if you have noticed I have written
int *pValue2(pValue1);
instead of
int *pValue2 = new int;
pValue2 = pValue1;
Still it is working and giving proper result.
Can any one explain to me which of the default function or constructor is getting called in this case?
int *pValue2(pValue1);
is equivalent to
int* pValue2 = pValue1;
Just assign to pValue2 pValue1 (assign to pValue2 address of variable value).
The difference should be apparent if you print the pointers themselves (the addresses) in addition to the values which they reference:
#include <iostream>
using namespace std;
int main() {
int value = 3;
int *pValue1 = &value;
int *pValue2(pValue1);
int *pValue3 = new int;
cout << pValue1 << " " << pValue2 << " " << pValue3 << endl;
cout << *pValue1 << " " << *pValue2 << " " << *pValue3 << endl;
pValue3 = pValue1;
cout << pValue1 << " " << pValue2 << " " << pValue3 << endl;
cout << *pValue1 << " " << *pValue2 << " " << *pValue3 << endl;
return 0;
}
You will also see that after new int, the memory pointed to by the pointer contains uninitialized data.

Pointer of int type moves 1 address in memory after incrementing it

The code works as expected until the lines 22-24, where we are printing 8 followed by address. Incrementing the pointer address increments the address by one byte only, whereas it should move address by 4 bytes. The problem does not occur in arrays or if lines 22-24 are run separately.
#include<iostream>
using namespace std;
void main()
{
int *p;
//int a[10] = { 0 };
//p = a;
int a = 100;
p=&a;
cout << "1. "<<p <<" "<<*p<< endl;
p++;
cout << "2. " << p << " " << *p << endl;
++p;
cout << "3. " << p << " " << *p << endl;
++*p;
cout << "4. " << p << " " << *p << endl;
++(*p);
cout << "5. " << p << " " << *p << endl;
++*(p);
cout << "6. " << p << " " << *p << endl;
*p++;
cout << "7. " << p << " " << *p << endl;
(*p)++; //This is the problem, increments the address by 1, even though its in int type
cout << "8. " << p << " " << *p << endl;
*(p)++;
cout << "9. " << p << " " << *p << endl;
*++p;
cout << "10. " << p << " " << *p << endl;
*(++p);
cout << "11. " << p << " " << *p << endl;
cin.get();
}
Initially you set p to point to an integer variable on the stack. When you subsequently increment the pointer you are pointing to an area of memory on the stack which is likely to change when a function is called ( cout for example). when the function returns it will probably have changed the memory location that your incremented pointer p is pointing to and this probably explains your issue.
You should declare an array large enough to accommodate the range of pointer addresses that you are going to step through. I notice that you commented out the array code which would have worked as you expected.
Your code is:
p = &a;
p++;
Now p is pointing past the end of a. This is still OK, however on the next line:
cout << "2. " << p << " " << *p << endl;
when you write *p this tries to read the memory past the end of a, which causes undefined behaviour.
When undefined behaviour has happened, the definition of the C++ language no longer covers what the program does. Anything can happen.
To put it another way: when generating the executable, the compiler can make assumptions based on the premise that your program only does things which are well-defined.
Your output could perhaps be explained by the compiler making such an assumption which would be justified if your program were confirming, but is actually false because your program is invalid.
One explanation that comes to mind is that you advanced p until it happens to be pointing to the memory location in which p itself is stored. The compiler implements (*p)++ by outputting an instruction for incrementing an int stored at the location where p is pointing. On your system, the result of applying this instruction to the location where actually p is stored is to increase the address value of p by one.