CERT.MEM.OBJ_LIFETIME_DTOR

手動で割り当てられたメモリを持つオブジェクトは明示的に破棄されない

CERT.MEM.OBJ_LIFETIME_DTOR チェッカーは、明示的に呼び出されない、非自明なデストラクター呼び出しを持つ、メモリが new 演算子なしで動的に割り当てられるユーザー定義オブジェクトを探します。

脆弱性とリスク

オブジェクトに非自明なデストラクターがあり、そのオブジェクトのメモリがヒープ上に割り当てられる場合、デストラクターを明示的に呼び出さずに、または delete 演算子を使用せずにメモリの割り当てを解除すると、デストラクターは呼び出されません。これは、デストラクターが管理するリソースを破棄するなどのタスクを実行する場合に問題になります。デストラクターを明示的に呼び出さなければ、それらの操作は実行されません。

軽減と防止

適合のための解決策は、メモリを管理する場合は new 演算子と delete 演算子を使用することです。そうすれば、delete 演算子によってオブジェクトのデストラクターが暗黙的に呼び出されるようになります。一方、デストラクターが非自明なものである場合は、明示的にデストラクターを呼び出すことを忘れないようにするという選択肢もあります。

脆弱コード例

コピー
#include <cstdlib>
 
struct S {
  ~S() { /* operations to destroy the object properly*/ }
  void f();
};
 
void g() {
  S *s = static_cast<S *>(std::malloc(sizeof(S)));
   
  std::free(s);
}

Klocwork で 9 行目について欠陥 CERT.MEM.OBJ_LIFETIME_DTOR が報告され、「動的に割り当てられ、's' によってポイントされているオブジェクトが明示的なデストラクター呼び出しによって破棄されない」ことが示されます。 このコードでは、ユーザー定義のデストラクターが暗黙的に呼び出されないため、メモリが解放されるまでは、デストラクターが実行するはずだった操作が発生しません。

修正コード例

コピー
#include <cstdlib>
 
struct S {
  ~S() { /* operations to destroy the object properly */ }
};
 
void g() {
S *s = static_cast<S *>(std::malloc(sizeof(S)));
s->~S();
std::free(s);
}

コードでデストラクターが明示的に呼び出されるので、欠陥が回避されるようになっています。

関連チェッカー