CERT.OOP.PTR_MEMBER.NO_MEMBER

メンバー演算子へのポインターを使用して、存在しないメンバーにアクセスしないでください。

メンバー演算子へのポインターを使用して、存在しないメンバーにアクセスしないでください。メンバー値の null ポインターを含めてください。

脆弱性とリスク

「pm-expression.*cast-expression」を「E1.*E2, E1」と省略する表記は、オブジェクト式と呼ばれます。E1 の動的な型に E2 が参照するメンバーが含まれないか、第 2 オペランドがメンバー値への null ポインターである場合、動作は不定になります。

軽減と防止

第 1 オペランドの動的な型に第 2 オペランドが参照するメンバーが含まれない場合、メンバー式へのポインターを使用しないでください (第 2 オペランドとしてのメンバー値への null ポインターも使用しない)。

コピー
  struct B1 {
    virtual ~B1() = default;
  };
  
  struct D1 : B1 {
    virtual ~D1() = default;
    virtual void g() { /* ...*/ }
  };
  
 void f1() {
   B1 *b = new B1;
 
   // ...
 
   void (B1::*gptr)() = static_cast<void(B1::*)()>(&D1::g);      //Non compliant
   (b->*gptr)();
   delete b;
 }
 
 struct B2 {
   virtual ~B2() = default;
 };
 
 struct D2 : B2 {
   virtual ~D2() = default;
   virtual void g() { /* ...*/ }
 };
 
 void f2() {
   B2 *b = new D2; // Corrected the dynamic object type.
 
   // ...
   void (D2::*gptr)() = &D2::g; // Moved static_cast to the next line.
   (static_cast<D2 *>(b)->*gptr)();
   delete b;
 }
 
 struct B3 {
   virtual ~B3() = default;
 };
 
 struct D3 : B3 {
   virtual ~D3() = default;
   virtual void g() { /* ...*/ }
 };
 
 static void (D3::*gptr3)(); // Not explicitly initialized: defaults to nullptr.Nonncompliant
 void call_memptr(D3 *ptr) {
   (ptr->*gptr3)();
 }
 
 void f3() {
   D3 *d = new D3;
   call_memptr(d);
   delete d;
 }
 
 struct B4 {
   virtual ~B4() = default;
 };
 
 struct D4 : B4 {
   virtual ~D4() = default;
   virtual void g() { /* ...*/ }
 };
 
 static void (D4::*gptr4)() = &D4::g; // Explicitly initialized.Compliant
 void call_memptr(D4 *ptr) {
   (ptr->*gptr4)();
 }
 
 void f4() {
   D4 *d = new D4;
   call_memptr(d);
   delete d;
 }