メインコンテンツ

割り当て関数または割り当て解除関数のオーバーロードが見つかりません

割り当て関数と割り当て解除関数のペアのうち 1 つの関数のみをオーバーロード

説明

この欠陥は、operator new をオーバーロードしたが対応する operator delete をオーバーロードしていない場合 (またはその逆の場合) に発生します。

リスク

通常、空きストアのメモリの割り当てに加えて何らかのブックキーピングを実行するために operator new をオーバーロードします。対応する operator delete をオーバーロードしていない場合は、メモリの割り当てを解除するときに対応するブックキーピングを省略した可能性があります。

この欠陥もコーディング エラーを示す可能性があります。たとえば、operator new[] の配置形式をオーバーロードしたとします。

void *operator new[](std::size_t count, void *ptr);
次のように operator delete[] の非配置形式を使用してしまう場合があります。
void operator delete[](void *ptr);
この場合は次の配置形式でなければなりません。
void operator delete[](void *ptr, void *p );

修正方法

operator new をオーバーロードする際、対応する operator delete を同じスコープでオーバーロードしていることを確認します (その逆も同様)。

たとえば、あるクラス内で operator new の配置形式をオーバーロードするとします。

class MyClass {
   void* operator new  ( std::size_t count, void* ptr ){
   ...
   }
};
operator delete の配置形式もオーバーロードしていることを確認します。
class MyClass {
   void operator delete  ( void* ptr, void* place ){
   ...
   }
};

operator new に対応する operator delete を見つける方法については、operator new および operator delete のリファレンス ページを参照してください。

すべて展開する

#include <new>
#include <cstdlib>

int global_store;

void update_bookkeeping(void *allocated_ptr, bool alloc) {
   if(alloc) 
      global_store++;
   else
      global_store--;
}


void *operator new(std::size_t size, const std::nothrow_t& tag);
void *operator new(std::size_t size, const std::nothrow_t& tag) {
    void *ptr = (void*)malloc(size);
    if (ptr != nullptr)
        update_bookkeeping(ptr, true);
    return ptr;
}

void operator delete[](void *ptr, const std::nothrow_t& tag);
void operator delete[](void* ptr, const std::nothrow_t& tag) {
    update_bookkeeping(ptr, false);
    free(ptr); 
}

この例では、演算子 operator new および operator delete[] はオーバーロードされていますが、対応する operator delete および operator new[] 演算子のオーバーロードがありません。

operator new のオーバーロードは、関数 update_bookkeeping を呼び出してグローバル変数 global_store の値を変更します。既定の operator delete が呼び出された場合、このグローバル変数は影響を受けませんが、これは開発者の想定に反する可能性があります。

修正 — operator delete の正しい形式をオーバーロード

operator new をオーバーロードする場合は、対応する形式の operator delete を同じスコープでオーバーロードします。

#include <new>
#include <cstdlib>

int global_store;

void update_bookkeeping(void *allocated_ptr, bool alloc) {
   if(alloc) 
      global_store++;
   else
      global_store--;
}


void *operator new(std::size_t size, const std::nothrow_t& tag);
void *operator new(std::size_t size, const std::nothrow_t& tag) {
    void *ptr = (void*)malloc(size);
    if (ptr != nullptr)
        update_bookkeeping(ptr, true);
    return ptr;
}

void operator delete(void *ptr, const std::nothrow_t& tag);
void operator delete(void* ptr, const std::nothrow_t& tag) {
    update_bookkeeping(ptr, false);
    free(ptr); 
}

結果情報

グループ: 適切な手法
言語: C++
既定値: オフ
コマンド ライン構文: MISSING_OVERLOAD_NEW_DELETE_PAIR
影響度: Low

バージョン履歴

R2019a で導入