C++リロードメモリ割り当て時の注意点
2505 ワード
テストコードを先に入力:
テスト1:
試験条件:
マクロVFおよびFLAGは定義されない
テスト結果:
テスト2:
試験条件:
マクロFLAGを定義するがマクロVFを定義しない
テスト結果:
テスト3:
試験条件:
マクロVFを定義するがマクロFLAGを定義しない
テスト結果:
テスト4:
試験条件:
マクロVFとFLAGを同時に定義する
テスト結果:
分析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を比較すると、ベースクラスの西溝関数を虚析構造関数として定義しないと、メモリ漏れが発生することがわかります.
#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を比較すると、ベースクラスの西溝関数を虚析構造関数として定義しないと、メモリ漏れが発生することがわかります.