I have a weird problem with a this-pointer in a base-class destructor.
Problem description:
I have 3 classes: A1, A2, A3
A2 inherits publicly from A1 and inherits privately from A3
class A2:private A3, public A1 {...}
A3 has a function getPrimaryInstance() ...that returns an A1-type reference to an A2 instance:
A1& A3::getPrimaryInstance()const{
static A2 primary;
return primary;
}
And the A3 constructor looks like this:
A3(){
getPrimaryInstance().regInst(this);
}
(Where regInst(...) is a function defined in A1 that stores pointers to all A3 instances)
Similarly the A3 destructor:
~A3(){
getPrimaryInstance().unregInst(this);
}
^Here is where the problem occurs!
When the static A2-instance named primary gets destroyed at program termination the A3-destructor will be called, but inside ~A3 I try to access a function on the same instance that I a destroying. => Access violation at runtime!
So I thought it would be possible to fix with a simple if-statement like so:
~A3(){
if(this != (A3*)(A2*)&getPrimaryInstance()) //Original verison
//if (this != dynamic_cast<A3*>(static_cast<A2*>(&getPrimaryInstance())))
//Not working. Problem with seeing definitions, see comments below this post
getPrimaryInstance().unregInst(this);
}
(Reason for double cast is the inheritance:)
A1 A3
. \ /
. A2
(But it's not important, could have just (int)-casted or whatever)
The kicker is that it still crashes. Stepping through the code with the debugger reveals that when my A2 primary-instance gets destroyd the this-pointer in the destructor and the address I get from calling getPrimaryInstance() doesn't match at all for some reason! I can't understand why the address that the this-pointer points to is always different from what it (to my limited knowledge) should be. :(
Doing this in the destructor:
int test = (int)this - (int)&getPrimaryInstance();
Also showed me that the difference is not constant (I briefly had a theory that there be some constant offset) so it's like it's two completely different objects when it should be the same one. :(
I'm coding in VC++ Express (2008).
And after googling a little I found the following MS-article:
FIX: The "this" Pointer Is Incorrect in Destructor of Base Class
It's not the same problem as I have (and it was also supposedly fixed way back in C++.Net 2003). But regardless the symptoms seemed much alike and they did present a simple workaround so I decided to try it out:
Removed the not-working-if-statement and added in virtual in front of second inheritance to A2, like so:
class A2:private A3, public A1 {...} // <-- old version
class A2:private A3, virtual public A1 {...} //new, with virtual!
AND IT WORKED! The this-pointer is still seemingly wrong but no longer gives an access-violation.
So my big question is why?
Why does the this-pointer not point to the where it should(?)?
Why does adding virtual to the inheritance like above solve it (despite this still pointing somewhere else than &getPrimaryInstance())?
Is this a bug? Can someone try it in a non-MS environment?
And most importantly: Is this safe?? Sure it doesn't complain anymore, but I'm still worried that it's not doing what it should. :S
If anyone has knowledge of or experience from this and could help me understand it I would be very thankful since I'm still learning C++ and this is entirely outside of my current knowledge.