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;
}