Main Content

CERT C++: OOP55-CPP

Do not use pointer-to-member operators to access nonexistent members

Since R2022a

Description

Rule Definition

Do not use pointer-to-member operators to access nonexistent members.1

Polyspace Implementation

The rule checker checks for Pointer to member accessing non-existent class members

Examples

expand all

Issue

This issue occurs when you use of pointer-to-member operators in these instances:

  • You cast a pointer-to-member type to another pointer-to-member type which does not contain the class member pointed to. For instance, in this code snippet, pointer-to-member ptrToMember is obtained from myObj::f but is then upcast to baseObj::* which does not contain a method f.

    class baseObj {
      public:
        virtual ~baseObj() = default;
    };
    
    class myObj : public baseObj {
      public:
        void f();
    };
    
    
    void func() {
        baseObj* foo = new baseObj();
        void (baseObj::*ptrToMember)() =
            static_cast<void (baseObj::*)()>(&myObj::f); //Noncompliant
        (foo->*ptrToMember)();
    }
    
    Polyspace® does not flag the casting operation if the type being cast to inherits from the other type. For example, in the preceding code, if baseObj inherits from myObj.

  • The second operand of the pointer-to-member operator is a null pointer. For instance, in this code snippet, ptrToMember is declared but not initialized and defaults to a null pointer.

    class baseObj {
      public:
        virtual ~baseObj() = default;
    };
    static void (baseObj::*ptrToMember)(); //Not initialized 
    
    void func() {
        baseObj* foo = new baseObj();
    
        (foo->*ptrToMember)(); //Noncompliant
    }
    

Risk

The use of pointer-to-member operators results in undefined behavior in these cases:

  • The dynamic type of the first operand does not contain the member referred to by the second operand.

  • The second operand pointer is null.

Fix

Do not cast a pointer-to-member to a type that does not contain the class member pointed to, and do not use a null pointer as the second operand of the pointer to member operator.

Example — Pointer-to-Member Accesses Non-Existent Class Member
class Base {
  public:
    void f() {
    }
};

class Derived : public Base {
  public:
    int myVar;
};

void func() {
    Base myObj;
    auto ptrToMethod =
        static_cast<void (Base::*)()>(&Derived::f); // Compliant
    auto ptrToMember =
        static_cast<int(Base::*)>(&Derived::myVar); // Noncompliant

    (myObj.*ptrToMethod)(); // OK, equivalent to myObj.f()
    myObj.*ptrToMember;     // Undefined behavior
}

In this example, Polyspace flags the casting of ptrToMember, which is obtained from Derived::myVar, to Base::* because this class does not contain a member myVar. If you execute the code, the call myObj.*ptrToMember; results in undefined behavior.

Polyspace does not flag the casting of ptrToMethod to Base::* because class Derived inherits method f from Base.

Correction — Use Correct Type for Underlying Object
class Base {
  public:
    void f() {
    }
};

class Derived : public Base {
  public:
    int myVar;
};

void func() {
    Derived myObj;
    auto ptrToMethod =
        static_cast<void (Base::*)()>(&Derived::f); // Compliant
    int (Derived::*ptrToMember) = &Derived::myVar; 

    (myObj.*ptrToMethod)(); // OK, equivalent to myObj.f()
    myObj.*ptrToMember; // Compliant  
}

One possible correction is to use the correct type for the object that you use as the first operator of the pointer-to-member operator. In the preceding code, myObj is of type Derived and the casting is no longer necessary in the declaration of ptrToMember.

Check Information

Group: Rule 09. Object Oriented Programming (OOP)

Version History

Introduced in R2022a


1 This software has been created by MathWorks incorporating portions of: the “SEI CERT-C Website,” © 2017 Carnegie Mellon University, the SEI CERT-C++ Web site © 2017 Carnegie Mellon University, ”SEI CERT C Coding Standard – Rules for Developing safe, Reliable and Secure systems – 2016 Edition,” © 2016 Carnegie Mellon University, and “SEI CERT C++ Coding Standard – Rules for Developing safe, Reliable and Secure systems in C++ – 2016 Edition” © 2016 Carnegie Mellon University, with special permission from its Software Engineering Institute.

ANY MATERIAL OF CARNEGIE MELLON UNIVERSITY AND/OR ITS SOFTWARE ENGINEERING INSTITUTE CONTAINED HEREIN IS FURNISHED ON AN "AS-IS" BASIS. CARNEGIE MELLON UNIVERSITY MAKES NO WARRANTIES OF ANY KIND, EITHER EXPRESSED OR IMPLIED, AS TO ANY MATTER INCLUDING, BUT NOT LIMITED TO, WARRANTY OF FITNESS FOR PURPOSE OR MERCHANTABILITY, EXCLUSIVITY, OR RESULTS OBTAINED FROM USE OF THE MATERIAL. CARNEGIE MELLON UNIVERSITY DOES NOT MAKE ANY WARRANTY OF ANY KIND WITH RESPECT TO FREEDOM FROM PATENT, TRADEMARK, OR COPYRIGHT INFRINGEMENT.

This software and associated documentation has not been reviewed nor is it endorsed by Carnegie Mellon University or its Software Engineering Institute.