I thought I was fairly good with C++, it turns out that I'm not. A previous question I asked: C++ const lvalue references had the following code in one of the answers:
#include <iostream>
using namespace std;
int& GenX(bool reset)
{
static int* x = new int;
*x = 100;
if (reset)
{
delete x;
x = new int;
*x = 200;
}
return *x;
}
class YStore
{
public:
YStore(int& x);
int& getX() { return my_x; }
private:
int& my_x;
};
YStore::YStore(int& x)
: my_x(x)
{
}
int main()
{
YStore Y(GenX(false));
cout << "X: " << Y.getX() << endl;
GenX(true); // side-effect in Y
cout << "X: " << Y.getX() << endl;
return 0;
}
The above code outputs X: 100, X:200. I do not understand why. I played with it a bit, and added some more output, namely, a cout before the delete x; and a cout after the new x; within the reset control block.
What I got was: before delete: 0x92ee018 after new: 0x92ee018
So, I figured that static was silently failing the update to x, and the second getX was playing with (after the delete) uninitialized memory; To test this, I added a x = 0; after the delete, before the new, and another cout to ensure that x was indeed reset to 0. It was.
So, what is going on here? How come the new returns the exact same block of memory that the previous delete supposedly free'd? Is this just because that's what the OS's memory manager decided to do, or is there something special about static that I'm missing?
Thank you!
That's just what the memory manager decided to do. If you think about it, it makes a lot of sense: You just freed an int, then you ask for an int again... why shouldn't the memory manager give you back the int you just freed?
More technically, what is probably happening when you
delete
is that the memory manager is appending the memory block you freed to the beginning of the free list. Then when you callnew
, the memory manager goes scanning through its free list and finds a suitably sized block at the very first entry.For more information about dynamic memory allocation, see "Inside storage allocation".
This makes perfect sense for the code.
Remember that it is your pointer that is static, so when you enter this function a second time you do not need to make a new pointer, but ever time you enter this function you are making a new int for the pointer to point to.
You are also probably in debug mode where a bit more time is spent giving you nice addresses.
Exactly why the int that your pointer points to is in the same space is probably just down to pure luck, that and you are not declaring any other variables before it so the same space in memory is still free
To your first question:
Since
Y.my_x
is just a reference to thestatic *x
inGenX
, this is exactly how it supposed it to be - both are referencing to the same address in memory, and when you change the content of *x, you get a side effect.i test your code in VC2008, the output is X: 100, X: -17221323. I think the reason is that the static x is freed. i think my test is reasonable.
You are accessing the memory block that is deallocated. By the c++ standard, that is an undefined behaviour, therefore anything can happen.
EDIT
I guess I have to draw :
EDIT2
The answer to why : implementation defined. The compiler can create new object at any location it likes.