I have a question about why I can access certain pieces of memory, and I think it has to do with the way I understand (or don’t understand) how the compiler saves things in memory. This is the sample code I’m working with:
The header file:
#include <iostream>
using namespace std;
class A
{
public:
int value;
A (int newValue = 5)
{
value = newValue;
cout << "A()" << endl;
}
~A() { cout <<"~A()" << endl; }
void func1() {cout << "A::func1()" << endl; }
};
class B : public A
{
public:
B() { A::value = 0; cout << "B()" << endl; }
~B() { cout << "~B()" << endl; }
virtual void func1 () { cout << "B::func1()" << endl; }
};
class C : public B
{
public:
C() { cout << "C()" << endl; }
~C() { cout << "~C()" << endl; }
virtual void func1() { cout << "C::func1()" << endl; }
};
The .cpp file:
int main()
{
int i;
cout << endl;
A* pA = new A (5);
B* pB = new B;
C* pC = new C;
pA->func1();
pB->func1();
pC->func1();
delete pA;
delete pB;
delete pC;
cout << endl;
//here is my first question - why don't I get a compiler error here?
//why does the compiler know what this is? Didn't I delete it?
A* ppA = pC;
//here is my second question - why does this work?
//didn't I clear this memory?
ppA->func1();
B bObject;
B* ppB = &bObject;
ppB->func1();
cin >> i;
return 0;
}
My questions are right there in the comments – why am I not getting errors on those lines?
If I change the .h file such that func1() is virtual in A as well, I do get an access violation on that line, but still no compile-time errors.
Thanks for any explanations 🙂
The answer to the first question is easy: the instruction is written at compile time. The compiler obviously won’t know whether that value has been deleted or not, so it just blindly copies the value of
pCoverppA.The answer to your second question is: it might not work. You have entered scary undefined-behavior-land. Think Alice in Wonderland, without the cat to guide you.
Basically when you call
operator deleteon a pointer, you’re telling the OS that it can overwrite the memory if needed. “If” needed. There’s no actual memory erasure going on, just a promise that you won’t be using that block of memory anymore.So when you try to access the virtual table to call
func1, the data might still be there. Or not. In which case you get a crash (if you’re lucky). But you deserve it, you broke your promise to the OS, so anything goes at this time.Edit: Note that
func1never actually usesthis, so if it wasn’t virtual you could have said((A*)0)->func1()and it would have worked fine.