C and C++


LANG.STRUCT.VCALL_IN_CTOR : Virtual Call in Constructor

Summary

A virtual member function is called from a constructor.

This can lead to unexpected and potentially dangerous behavior. During execution of a base class B's constructor, when not in an even deeper base class's constructor, any virtual calls through the this pointer will resolve as if B is the dynamic type (most derived type) of this.

For inline constructors, a warning will only be issued if the constructor is invoked at least once.

Properties

Class Name Virtual Call in Constructor
Significance reliability
Mnemonic LANG.STRUCT.VCALL_IN_CTOR
Categories
AUTOSARC++14 AUTOSARC++14:M12-1-1 An object's dynamic type shall not be used from the body of its constructor or destructor.
MisraC++2008 MisraC++2008:12-1-1 An object's dynamic type shall not be used from the body of its constructor or destructor.
MisraC++2023 MisraC++2023:15.1.1 An object's dynamic type shall not be used from within its constructor or destructor
CWE CWE:1419 Incorrect Initialization of Resource
CERT-CPP CERT-CPP:OOP50-CPP Do not invoke virtual functions from constructors or destructors
JSF++ JSF++:70.1 An object shall not be improperly used before its lifetime begins or after its lifetime ends.
  JSF++:71 Calls to an externally visible operation of an object, other than its constructors, shall not be allowed until the object has been fully initialized.
  JSF++:71.1 A class's virtual functions shall not be invoked from its destructor or any of its constructors.
Availability Available for C++ only (not C).
Enabling Checks for this warning class are enabled by default. To disable them, add the following WARNING_FILTER rule to the project configuration file.
WARNING_FILTER += discard class="Virtual Call in Constructor"

Example

namespace lang_struct_vcall_in_ctor {

  // Code with explicit inline constructor invocation. 

  class BaseExplicit {
      virtual void virtual_setup(void) {}
    public:
      BaseExplicit() {
          this->virtual_setup(); // 'Virtual Call in Constructor' warning issued here.
                                 //   This call to virtual_setup() will always invoke BaseExplicit::virtual_setup(),
                                 //   which is probably not what the author intends.
      }
  };

  class DerivedExplicit : BaseExplicit {
      int i;
      virtual void virtual_setup(void) override {i=5;}
  };

  BaseExplicit * use_base_explicit(void){
      BaseExplicit *be = new BaseExplicit();           // Explicit invocation of inline constructor.
      return be;
  }

  // Code with implicit inline constructor invocation. 

  class BaseImplicit {
      virtual void virtual_setup(void) {}
    public:
      BaseImplicit() {
          this->virtual_setup();  // Two 'Virtual Call in Constructor' warnings issued here
                                  // - one for the virtual call in BaseImplicit::BaseImplicit()
                                  // - one for the virtual call in DerivedImplicit::DerivedImplicit()
      }
  };

  class DerivedImplicit : BaseImplicit {
      int i;
      virtual void virtual_setup(void) override {i=5;}
    public:
      int value(void){
          return i;               // 'Uninitialized Variable' warning issued here 
                                  //   - when use_derived_implicit() calls d.value(), the issues with the virtual
                                  //     call in the constructor mean that d.i has NOT actually been initialized.
      }
  };

  int use_derived_implicit(void){
      DerivedImplicit d;                               // Implicit invocation of inline BaseImplicit constructor
                                                       // (and then DerivedImplicit constructor).
      return d.value();
  }
}

Relevant Configuration File Parameters

The following configuration file parameters affect checks for this warning class.