You are viewing an old version of this page. View the current version.

Compare with Current View Page History

« Previous Version 43 Next »

Deleting a derived class object using a pointer to a base class that has a non-virtual destructor results in undefined behavior. To correct this situation, the base class should be defined with a virtual destructor.

Non-Compliant Code Example

In this non-compliant example, a pointer to the base class Base is used to refer to a Derived object. When b is deleted, undefined behavior results. Typically, the destructor for Base is invoked rather than the destructor for Derived. As a result, the object b refers to is not properly destroyed.

class Base {
public:
   Base() {
      // Build Base object
   }
   ~Base() {
      // Destroy Base object
   }
};

class Derived : public Base {
public:
   Derived() {
      // Build Derived object
   }
   ~Derived() {
      // Destroy Derived object
   }
};

void function(void) {
   Base *b = new Derived();
   // ...
   delete b;
}

Compliant Solution

To correct this example, the destructor for Base should be declared virtual. This ensures that the object b refers to is correctly evaluated at runtime and that deleting b will call the destructor for class Derived.

class Base {
public:
   Base() {
      // Build Base object
   }
   virtual ~Base() {
      // Destroy Base object
   }
};

class Derived : public Base {
public:
   Derived() {
      // Build Derived object
   }
   ~Derived() {
      // Destroy Derived object
   }
};

void function(void) {
   Base *b = new Derived();
   // ...
   delete b;
}

Destructors are not virtual by default because many classes are not designed to be used as base classes. Additionally, many base classes are used only for reasons of implementation, and are not used in a polymorphic fashion. Virtual functions only make sense in classes that act as interfaces to objects of derived classes.

Risk Assessment

Calling the wrong destructor for a polymorphic object may lead to undefined behavior. In practice, potential consequences include abnormal program termination and resource mismanagement.

Rule

Severity

Likelihood

Remediation Cost

Priority

Level

OBJ34-CPP

2 (medium)

2 (probable)

2 (medium)

P8

L2

Automated Detection

Klocwork can detect violations of this rule with the CL.MLK.VIRTUAL checker.  See Klocwork Cross Reference

References

*[[Stroustrup 06]] Why are destructors not virtual by default?


OOP33-CPP. Do not slice polymorphic objects      13. Object Oriented Programming (OOP)      VOID 14. Templates and the STL (STL)

  • No labels