Reputation: 349
Here is some C++ code.
#include <iostream>
using namespace std;
class test{
int a;
public:
test(int b){
a = b;
cout << "test constructed with data " << b << endl;
}
void print(){
cout << "printing test: " << a << endl;
}
};
test * foo(){
test x(5);
return &x;
}
int main()
{
test* y = foo();
y->print();
return 0;
}
Here is its output:
test constructed with data 5
printing test: 5
My question: Why does the pointer to x still "work" outside of the context of function foo? As far as I understand, the function foo creates an instance of test and returns the address of that object.
After the function exits, the variable x is out of scope. I know that C++ isn't garbage collected- what happens to a variable when it goes out of scope? Why does the address returned in foo() still point to what seems like a valid object?
If I create an object in some scope, and want to use it in another, should I allocate it in the heap and return the pointer? If so, when/where would I delete it
Thanks
Upvotes: 5
Views: 304
Reputation: 8861
x
is a local variable. After foo
returns there's no guarantee that the memory on the stack that x
resided in is either corrupt or intact. That's the nature of undefined behavior. Run a function before reading x
and you'll see the danger of referencing a "dead" variable:
void nonsense(void)
{
int arr[1000] = {0};
}
int main()
{
test* y = foo();
nonsense();
y->print();
return 0;
}
Output on my machine:
test constructed with data 5
printing test: 0
Upvotes: 8
Reputation: 75696
When a variable goes out of scope, the destructor is called (for non POD data) and the location occupied by that variable is now considered unallocated, but the memory isn't actually written, so the old value remains. This doesn't mean that you can still safely access this value because it resides in a location marked as 'free'. New variables can reside or allocation can occur in this memory space.
The reason why the memory isn't erased is because you can't actually erase memory, what you could do is write something to it like all zeros or all ones or random, which is not only pointless, but performance-degrading.
It has nothing to do with garbage-collection. A garbage collector doesn't "erase" memory, but marks it as being free. The reason why the behaviour you described exists in C and not in Java for instance is not the garbage-collector, but the fact that C lets you access via pointers any memory you want, allocated or not, valid or not, and Java doesn't (To be fair the garbage collector is a reason why Java can make so that you can't access any memory).
An analogy can be made with what happens on disk when you delete a file. The file contents remain (they are not overwritten), but instead pointers (handles) in the file system are modified so that that memory on the disk is considered free. That's why special tools can recover deleted files: the information is still there until something new writes over it, and if you can point to it you can obtain it. Is almost the same thing with pointers in C. Think what would it mean to actually write 4GB on disk every time you delete a 4GB file. There is no need to write in memory for each variable that goes out of scope the entire size of that variable. You just mark it's free.
Upvotes: 3