Here is the program producing the error:
#include <iostream>
#include <string>
using namespace std;
class Pet {
protected:
string name;
public:
Pet(string nam):name(nam){}
~Pet(){cout<< "Pet destroyed" << endl;} // attention
void play();
};
void Pet::play(){
std::cout<< "Pet " << name <<" is playing ..." <<endl;
}
class Cat : public Pet {
public:
Cat(string nam):Pet(nam){}
~Cat(){cout<< "Cat destroyed" <<endl;}
void play();
};
void Cat::play(){
cout<< "cat " << name <<" is playing ..." <<endl;
}
class Dog : public Pet {
public:
Dog(string nam):Pet(nam){}
~Dog(){cout<< "Dog destroyed" <<endl;}
virtual void play(); // attention
};
void Dog::play(){
cout<< "dog " << name <<" is playing ..." <<endl;
}
int main(void) {
Pet *cat1 = new Cat("Kitty");
Pet *dog1 = new Dog("Tom");
Pet *pet = new Pet("Nicky");
cat1->Pet::play();
dog1->play();
pet->play();
delete cat1;
delete pet;
delete dog1;
return 0;
}
This program just compiles fine, but when I run it I got the following output:
Pet Kitty is playing ...
Pet Tom is playing ...
Pet Nicky is playing ...
Pet destroyed
Pet destroyed
Pet destroyed
t(35634,0x7fff7ae04310) malloc: *** error for object 0x7f8623c03b68: pointer being freed was not allocated
*** set a breakpoint in malloc_error_break to debug
Abort trap: 6
The results before the error information just make sense, but I couldn't understand why I got this error. The error produces at the line delete dog1;
. 0x7f8623c03b68 is the address of the object dog1. Since dog1->play();
just executes fine, the memory space for object dog1 should be well allocated. Why does the error says "pointer being freed was not allocated"???
When I change the destructor of class Pet to be virtual, the program executes fine without errors. Why??? Here is the output:
Pet Kitty is playing ...
Pet Tom is playing ...
Pet Nicky is playing ...
Cat destroyed
Pet destroyed
Pet destroyed
Dog destroyed
Pet destroyed
In this case, when delete dog1, the destructor of Dog will first be called then the destructor of Pet. So what differences concerning the changes in memory does the word "virtual" make in these two cases?
In this article Why should I declare a virtual destructor for an abstract class in C++? it explains that when the destructor of a base class is not declared virtual, when delete a pointer of base class type that referring to a subclass object, un Undefined behavior will be produced. So is this error just an example of the so called Undefined behavior? Since when I removed the virtual from the class Dog, the program executes well.
I am note sure if it's a duplicated question as the problem mentioned in the above article. Just want to make sure and find the reason for that error.
Any instructions will be welcomed. Thanks.