C++リロードメモリ割り当て時の注意点

2505 ワード

テストコードを先に入力:
#include <stdio.h>
#include <malloc.h>
#include <new>

//#define VF
//#define FLAG

class MemObj
{
public:
#ifdef VF
  virtual MemObj(void) {}
#endif // VF
  
  static void* operator new(size_t stSize)
  {
    printf("operator new(size_t) %d
", stSize); return malloc(stSize); } #ifdef FLAG static void operator delete(void* pMemory) { printf("operator delete(void*)
"); free(pMemory); } #endif static void operator delete(void* pMemory, size_t stSize) { printf("operator delete(void*, size_t) %d
", stSize); free(pMemory); } }; class Test : public MemObj { private: int m_nValue; }; int main(int argc, char** argv) { MemObj* pObj = new MemObj(); delete pObj; Test* pTest = new Test(); delete pTest; pObj = new Test(); delete pObj; return 0; }

テスト1:
試験条件:
マクロVFおよびFLAGは定義されない
テスト結果:
operator new(size_t) 1
operator delete(void*, size_t) 1
operator new(size_t) 4
operator delete(void*, size_t) 1
operator new(size_t) 4
operator delete(void*, size_t) 1

テスト2:
試験条件:
マクロFLAGを定義するがマクロVFを定義しない
テスト結果:
operator new(size_t) 1
operator delete(void*)
operator new(size_t) 4
operator delete(void*)
operator new(size_t) 4
operator delete(void*)

テスト3:
試験条件:
マクロVFを定義するがマクロFLAGを定義しない
テスト結果:
operator new(size_t) 4
operator delete(void*, size_t) 4
operator new(size_t) 8
operator delete(void*, size_t) 8
operator new(size_t) 8
operator delete(void*, size_t) 8

テスト4:
試験条件:
マクロVFとFLAGを同時に定義する
テスト結果:
operator new(size_t) 4
operator delete(void*)
operator new(size_t) 8
operator delete(void*)
operator new(size_t) 8
operator delete(void*)

分析1:
テスト1とテスト2を比較すると、operator new(size_t stSize)がリロードされた後、削除時にvoid operator delete(void*pMemory)が定義されていなければvoid operator delete(void*pMemory,size_t stSize)が呼び出され、void operator delete(void*pMemory,size_t stSize)が定義されていれば、void operator delete(void*pMemory)が定義され、void operator delete(void*pMemory,size_t stSize)を定義するかどうかにかかわらず、void operator delete(void*pMemory)が呼び出されます.
結論1:
operator new(size_t)をリロードした後、operator delete(void*)を同時にリロードした場合、削除時にoperator delete(void*)が呼び出されます.そうしないとoperator delete(void*,size_t)が呼び出されます.
分析2:
テスト1とテスト3を比較すると、ベースクラスの西溝関数を虚析構造関数として定義しないと、メモリ漏れが発生することがわかります.