Deleted variable can still be accessed in c++? [duplicate] - c++

This question already has answers here:
C++ delete - It deletes my objects but I can still access the data?
(13 answers)
Closed 1 year ago.
The community reviewed whether to reopen this question 1 year ago and left it closed:
Original close reason(s) were not resolved
I created a simple project just to test how deleting variable works but i encountered a strange thing...
I created three int variables (1 stack based and 2 heap based) and when i deleted the heap variables using delete i still could access them. I can print them or change their value but how? Isn't delete supposed to permanently delete the variable from memory and also another question.... Why stack based variables can't be deleted using free() or delete?
Here is the (C++) script -
#include<iostream>
using namespace std;
void Stuff()
{
int* heap_int = (int*)malloc(4); //Heap based variable
*heap_int = 500;
int stack_int = 5; //Stack based variable
int* calloc_int = (int*)calloc(1,2); //Heap based variable
*calloc_int = 600;
std::cout << "Value (HeapInt) : " << *heap_int << "\n"; //Prints 500
std::cout << "Value (CallocInt) : " << *calloc_int << "\n"; //Prints 600
std::cout << "Value (StackInt) : " << stack_int << "\n"; //Prints 5
delete heap_int;
delete calloc_int;
//delete stack_int; (will not work)
std::cout << "\nValue after delete (HeapInt) : " << *heap_int << "\n"; //Still prints 500
std::cout << "Value after delete (CallocInt) : " << *calloc_int << "\n"; //Still Prints 600
std::cout << "Value after delete (StackInt) : " << stack_int << std::endl; //Prints 5
*heap_int = 82;
}
int main()
{
Stuff();
}
I heard in online tutorials that heap based variables only get freed if we used delete or free() (unlike stack variables who get freed automatically when their scope ends) then why can't i access an heap based variable out of scope like this...?
#include<iostream>
void Function()
{
int* variable = new int;
*variable = 6;
}
int main()
{
*variable = 9; //Error says "Use of Undeclared identifier variable"
}

Reading the contents of a free'd or deleted memory address is called undefined behavior.
delete heap_int;
std::cout << "\nValue after delete (HeapInt) : " << *heap_int << "\n"; //Still prints 500
You might still be able to see the previous value at a deleted address, but it's definitely not guaranteed. As soon as the next malloc/new happens (or technically at any time), the memory manager might re-use that address for another object and overwrite what's there.
And this:
*heap_int = 82;
Similarly, writing to a deleted address is even worse undefined behavior - chances are high you have corrupted your program's behavior in strange ways, or at best, a fast crash.
why can't i access an heap based variable out of scope like this...?
Because you can't access any variable that's not in your scope or the parent scope. In your case, code in main can only access variables in that function or variables declared at global scope. That's the whole point of scope!

Related

Is this a double free in C++

I thought the following code snippets would cause double free, and the program would core dump. But the truth is that there is no error when I run the code?
Similar problem shows that it caused double free!
My Question is why does there have no error show that there is a double free? And why does there have no core dump?
#include <iostream>
using namespace std;
int main()
{
int *p = new int(5);
cout << "The value that p points to: " << (*p) << endl;
cout << "The address that p points to: " << &(*p) << endl;
delete p;
cout << "The value that p points to: " << (*p) << endl;
cout << "The address that p points to: " << &(*p) << endl;
delete p;
cout << "The value that p points to: " << (*p) << endl;
cout << "The address that p points to: " << &(*p) << endl;
delete p;
}
The program's output when I ran this program is shown as followed:
After modifying the code snippet like the following, the core dump occured:
#include <iostream>
using namespace std;
int main()
{
int *p = new int(5);
for (;;)
{
cout << "The value that p points to: " << (*p) << endl;
cout << "The address that p points to: " << &(*p) << endl;
delete p;
}
return 0;
}
And the program output is :
So there is another question that why this program will core dump every time?
Yes, it is a double free (well, triple, really) which puts it into undefined behaviour territory.
But that's the insidious thing about undefined behaviour, it's not required to crash or complain, it's not required to do anything at all(a). It may even work.
I can envisage an implementation that stores the free state of a block in the control information for it so that freeing it twice would have no effect. However, that would be inefficient, and also wouldn't cover the case where it had been reallocated for another purpose (it would prevent double frees, but not a piece of code freeing the block when some other piece still thinks it still has it).
So, given it's not required to work, you would be well advised to steer clear of it since it may also download maniacal_laughter.ogg and play it while erasing your primary drive.
As an aside, modern C++ has smart pointers that are able to manage their own lifetime, and you would be doing yourself a big favour if you started using those instead of raw pointers.And, although the removal of raw pointer from C++ was a joke, there are some that think it's not such a bad idea :-)
(a) The C++20 standard has this to say when describing undefined behaviour in [defns.undefined] (my emphasis):
Behavior for which this document imposes **NO** requirements.
why does there have no error show that there is a double free? And why does there have no core dump?
delete p;
cout << "The value that p points to: " << (*p) << endl;
The moment you referenced to a deleted pointer is when the program entered an undefined behaviour, and then there is no guarantee that there would be an error or a crash.
It's not entirely the same, but the analogy between memory and a hotel room is applicable, which explains well what an undefined behaviour means. Highly recommended reading:
Can a local variable's memory be accessed outside its scope?

Would there be any possible issues with declaring a pointer value in separate lines in C++, instead of using the 'new' function?

I'm new to C++ and currently having a hard time with pointers.
I was wondering if there is a preferred method of coding between the two methods shown below:
#include <iostream>
using namespace std;
int main(){
// method 1
int* n;
*n = 2;
cout << "address of n in main(): " << n << "\n"; //returns 0
cout << "value inside of n in main(): " << *n << "\n"; // returns 2
// method 2
int* m = new int(2);
cout << "address of m in main(): " << m << "\n"; //returns some address
cout << "value insdie of m in main(): " << *m << "\n"; // returns 2
}
The first method returns the following:
address of n in main(): 0
value inside of n in main(): 2
The Second method returns the following:
address of m in main(): 0x6c2cc0
value inside of m in main(): 2
Q1. What would be possible issues with having the address of n in main():0? (it only behaves like this on an online compiler sorry. Nevermind this question.)
Q2. What is the "new" declaration method called?
What would be possible issues with having the "address of n in main():0"?
If you are lucky, crashing the program due to segfault. If you are not, memory corruption, undefined behavior, etc.
The reason is that you are using an effectively random memory address that has not been mapped/reserved/allocated to your process.
What is the "new" declaration method called?
There is no "name" for the "method". new is a keyword and an operator, too. It is the standard way of allocating memory in C++. Although, in almost all cases, you will use a container instead that manages the memory for you, like std::vector or std::unique_ptr.

C++ program's assertion failure due to deleting a pointer [duplicate]

This question already has answers here:
Delete and invalid pointer
(2 answers)
Closed 8 years ago.
I have created an int variable.
Then I have assigned it to a pointer.
After that, I cout-ed it and then eventually I deleted.
What happens? The console pops up, but then immediately an error dialog box appear with the error Assertion Failure. Can any one explain why I receive the error? Here is the code:
int main()
{
int mainNum = 10;
int *numPt;
numPt = &mainNum;
cout << &numPt;
delete(numPt);
cout << endl << endl << endl; // this is to secure last newline char to be outputted.
cout << "---------------------------" << endl;
return 0;
}
You cannot delete stuff that is on the stack. You can only delete stuff that is on the heap (created by new). Otherwise all sorts of stuff will happen

Strange behavior of pointers in c++

Following results are very interesting and I am having difficulty understanding them. Basically I have a class which has an int:
class TestClass{
public:
int test;
TestClass() { test = 0; };
TestClass(int _test) { test = _test; };
~TestClass() { /*do nothing*/ };
};
A test function which accepts a pointer of TestClass
void testFunction1(TestClass *ref){
delete ref;
TestClass *locTest = new TestClass();
ref = locTest;
ref->test = 2;
cout << "test in testFunction1: " << ref->test << endl;
}
This is what I am doing in main:
int main(int argc, _TCHAR* argv[])
{
TestClass *testObj = new TestClass(1);
cout << "test before: " << testObj->test << endl;
testFunction1(testObj);
cout << "test after: " << testObj->test << endl;
return 0;
}
I was expecting output to be:
test before: 1
test in testFunction1: 2
test after: 1
But I get the following output:
test before: 1
test in testFunction1: 2
test after: 2
Can someone explain this. Interesting thing is that changing testFunction1 to:
void testFunction1(TestClass *ref){
//delete ref;
TestClass *locTest = new TestClass();
ref = locTest;
ref->test = 2;
cout << "test in testFunction1: " << ref->test << endl;
}
i.e. I do not delete ref before pointing it to new location, I get the following output:
test before: 1
test in testFunction1: 2
test after: 1
I would really appreciate if someone can explain me this strange behavior. Thanks.
When you access the object after deleting it, the behaviour is undefined.
The behaviour that you see follows from the memory allocation algorithm in your system.
That is after deleting your first testclass object, you allocate memory for a new object. The runtime simply reuses the memory.
To check what is going on, print the values of the pointers:
void testFunction1(TestClass *ref){
cout << ref << endl;
delete ref;
TestClass *locTest = new TestClass();
cout << locTest << endl;
ref = locTest;
ref->test = 2;
cout << "test in testFunction1: " << ref->test << endl;
}
You get a copy of the pointer to the object in testFunction1(), so when you assign to it, the original value of the pointer in main() does not change
Also, you are deleting the object (by calling delete in testFunction1()) to which the original pointer (in main()) is pointing, but as the value in main() is not updated, you are accessing an invalid object -- the fact that you can read the value that you set in testFunction1(), is a coincidence and cannot be relied on
The fact that you correctly read the original value in the second case (when you don't call delete) is because the original object has not been changed (you change a new one in testFinction1 and the pointer to it in main is the same (as explained above) and the object is still alive
in this case , you just got the new object at the same address with the old one you delete.
actually testObj became a dangling pointer after you call testFunction1.
void testFunction1(TestClass *ref){
delete ref;
TestClass *locTest = new TestClass();
cout << "locTest = " << locTest << endl;
ref = locTest;
ref->test = 2;
cout << "test in testFunction1: " << ref->test << endl;
}
int main(int argc, char * argv[])
{
TestClass *testObj = new TestClass(1);
cout << "test before: " << testObj->test << endl;
cout << "testObg = " << testObj << endl;
testFunction1(testObj);
cout << "test after: " << testObj->test << endl;
cout << "testObg = " << testObj << endl;
return 0;
}
Output is :
test before: 1
testObg = 0x511818
locTest = 0x511818
test in testFunction1: 2
test after: 2
testObg = 0x511818
After this instruction:
TestClass *testObj = new TestClass(1);
you have allocated a new memory area containing a TestClass object, whose address (let's call it maddr) is stored into testObj.
Now, this instruction:
cout << "test before: " << testObj->test << endl;
outputs 1, as expected.
Inside testFunction1() you have a local variable called ref, which is a pointer containing the value maddr.
When you delete ref, you deallocate the area of memory containing a TestClass object, whose address is maddr.
Then you allocate a new memory area:
TestClass *locTest = new TestClass();
and locTest contains its address, let's call it m1addr.
Then you use ref to access the memory area at m1addr and change the int test value to 2.
This instruction:
cout << "test in testFunction1: " << ref->test << endl;
outputs 2 as expected.
Now, back to main, you have lost any handler to the area containing a TestClass object whose address is m1addr (that is, you are leaking memory) and the area pointed to by testObj is not allocated anymore.
When you use testObj again, you access an area of memory starting at maddr, which has been cleaned. The effect of accessing testObj->test is undefined behavior.
What you experience could be do to the fact that when you run your code maddr == m1addr, but this can only happen by chance, you cannot rely on this.
Odds are the new object (with a 2) is being created where the old deleted object (with a 1) used to be. Your original pointer still points to that location so when you access it you accidentally access the new object (with a 2).
TestClass *ref in the parameter to testFunction1 and TestClass *testObj in main are 2 different pointers to the same thing, they are not the same pointer though. If you want to delete and reallocate an object inside a function/method you can use a pointer to a pointer as the parameter.
As others have mentioned , after testfunction1 you're accessing an object that was deleted within testfunction1 which as also mentioned is undefined behaviour. The memory being pointed to by the dangling pointer was released during the delete but the contents are likely to still be there until the memory location is reallocated during another call to new. So you are using unallocated space that could be overwritten very easily at anytime.
Hope this helps

Deleting a pointer to an automatic variable [duplicate]

This question already has an answer here:
What is the behavior of "delete" with stack objects? [duplicate]
(1 answer)
Closed 8 years ago.
Please look at this code
int i = 10; //line 1
int *p = &i; //line 2
delete p; //line 3
cout << "*p = " << *p << ", i = " << i << endl; //line 4
i = 20; //line 5
cout << "*p = " << *p << ", i = " << i << endl; //line 6
*p = 30; //line 7
cout << "*p = " << *p << ", i = " << i << endl; //line 8
What is the result of this code? Especially of line 3, 5 and 7? Do they invoke undefined behavior? What would be the output?
EDIT : I tried running it using g++, and it's compiling and running fine! I'm using MinGW on Windows 7.
What does Standard say in this context?
You can delete only a pointer if you have ever allocated it dynamically using new. In this case you have not allocated the pointer using new but simply defined and initialized it to point to a local variable of type int.
Invoking delete on a pointer not allocated dynamically using new is something called Undefined Behavior. In short, it means that anything on the earth can happen when such a code is executed and you can't complaint a bit to anyone on this planet.
delete p; is UB and so any further behavior can't be predicted or relied upon. You program might crash immediately or spend all your money or just exit from main() and pretend nothing happened.
Line 3 is definitely undefined behaviour, since you're trying to deleting memory at an address that is not on the heap.