EN JP CN

CWARN.DTOR.NONVIRT.NOTEMPTY

CWARN.DTOR.NONVIRT.NOTEMPTY

クラスでは仮想関数が継承されますが、デストラクタは仮想ではなく、空ではありません

CWARN.DTOR.NONVIRT.NOTEMPTY チェッカーは、クラスで、その基本クラスから継承される仮想メンバー関数を宣言するが、デストラクタは仮想ではなく、空でもないクラスにフラグを立てます。

脆弱性とリスク

基本クラスから派生したクラスのオブジェクトを、その基本クラスを指すポインターを介して削除する場合、その派生クラスのデストラクタは実行されません。そして、その派生クラスのメンバーは適切に破棄されません。このような状況により、メモリのリークやリソースが解放されないといった問題につながる可能性があります。

軽減と防止

仮想メソッドと、暗黙的または明示的に適切に破棄する必要のあるメンバーデータを含むクラスに仮想デストラクタ (空であっても) を用意することが重要です。派生クラスは、基本クラスから継承します。基本クラスのデストラクタが仮想として定義されていない場合、メモリは適切に割り当て解除されません。仮想関数を宣言する、またはオーバーライドするクラスの階層では、仮想デストラクタは、その階層のルートクラスに対して 1 回だけ定義する必要があります。

脆弱コード例

1   #include <iostream>
2   using namespace std; 
3    
4   class A
5   {
6   public:
7    
8       ~A() {std::cout << "I am A" << std::endl;}
9       virtual void f1();
10  };
11   
12  class B : public A
13  {
14  public:
15   
16      ~B() {cout << "I am B" << endl;} 
17      virtual void f1();
18  };

このコード例では、クラス A の非仮想デストラクタは、Klocwork が 16 行目にフラグを立てることを意味します。