首页
社区
课程
招聘
[原创]自动delete 或 Release
发表于: 2011-3-27 16:23 9807

[原创]自动delete 或 Release

2011-3-27 16:23
9807

用了一天时间,终于搞出来这个能自动delete 或 Release 的函数!

有些该 Release 的指针,如果 delete 就会运行错.这个bug不容易排查.

如果能有一个函数,自动根据指针的类型,智能选择使用 delete 还是 Release,
就可以省不少事.

查了关天资料,看了半天boost::is_base_of代码,却原来是C++支持的 __is_base_of
再用模板写出来,OK!

WinMount 继续招程序员!简历请发 support@winmount.com


[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

收藏
免费 7
支持
分享
最新回复 (8)
雪    币: 1708
活跃值: (586)
能力值: ( LV15,RANK:670 )
在线值:
发帖
回帖
粉丝
2
__is_base_of 好像是编译器来支持的, 不是标准C++的一部份。
模板的重载。
2011-3-28 10:10
0
雪    币: 440
活跃值: (119)
能力值: ( LV6,RANK:80 )
在线值:
发帖
回帖
粉丝
3
受教了,查了下msdn,解释如下:

Returns true if the first type is a base class of the second type, of if both types are the same.

__is_base_of also works on CLR types. For example, it will return true if the first type is an interface class and the second type implements the interface.

// is_base_of.cpp
#include <stdio.h>
struct S {};
struct T : public S {};

int main() {
   __is_base_of(S, T) == true ?
      printf("true\n") : printf("false\n");

   __is_base_of(S, S) == true ?
      printf("true\n") : printf("false\n");
}
2011-3-28 13:49
0
雪    币: 1708
活跃值: (586)
能力值: ( LV15,RANK:670 )
在线值:
发帖
回帖
粉丝
4
什么情况只能 Release ?什么时候才 Delete ?
2011-3-31 18:04
0
雪    币: 306
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
涛哥,Release实际不是调用的delete吗
2011-3-31 18:08
0
雪    币: 1708
活跃值: (586)
能力值: ( LV15,RANK:670 )
在线值:
发帖
回帖
粉丝
6
Release 是对象的引用数减一,减到零对象就over了。
delete 是直接干掉对象。
进程间的组件才要 release 。进程内的可以直接delete。印象中书上是这么说的.

涛哥的这个代码应该是用来自动识别一般指针和COM指针用的。
2011-3-31 18:29
0
雪    币: 1644
活跃值: (53)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
方法很巧妙,学习。不过本该Release的指针怎么会去delete呢, 是开发的人不知道自己在做什么吗?
2011-5-9 15:44
0
雪    币: 143
活跃值: (61)
能力值: ( LV5,RANK:70 )
在线值:
发帖
回帖
粉丝
8
从来不release 的用MFC的路过~~~
2011-5-12 23:12
0
雪    币: 89
活跃值: (53)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
这个代码我前几天看到过一份类似的,也是用哦模板实现,
作者是个韩国人,在codeporject上找到的。


// VMemPool.h: interface for the CVMemMan class.
//
// Virtual Memory Pool Management Class
// by bro (bro@shinbiro.com)
// (Cho,Kyung-min)
// 2002-02-19
//
//--------------------------------------------------------------------
// History.
// 2002-02-19 : Fisrt Code.
// 2002-02-20 : vmXXX public Function supported 
//              DEBUG_NEW supported ( but not impl yet.. )
// 2002-03-08 : New mechanism : alloc bitset, not use std::list is so heavy.
//              just i use 'Free-MemoryBlock-Queue'
//              Support Helper Function: IsBadPtr.
//--------------------------------------------------------------------
// Manual
// Usage
/*

class CObj : public CVMemPool<>
{
public:
   :
};

CObj* pObj = new CObj; // Virtual Memory Pool 1000 blocks created, allocated 1st block
CObj* pObj2 = new CObj;// allocated second block
delete pObj;           // first block deleted
delete pObj2;          // second block deleted

*//////////////////////////////////////////////////////////////////////

#if !defined(AFX_VMEMPOOL_H__BD52675B_6C82_4CDE_8618_0141D7A4653F__INCLUDED_)
#define AFX_VMEMPOOL_H__BD52675B_6C82_4CDE_8618_0141D7A4653F__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

#include "BitSet.h"
//====================================================================
// CVMemPool<int T> : Virtual Memory Pool Management Class
//--------------------------------------------------------------------
// Virtual Memory Pool for managing same object block
//====================================================================
template <class objT,DWORD _dwPoolSizeT = 1000>
class CVMemPool  
{
public:
	//===========================================================
	// Name   : vmInitPool
	// Desc   : Initilize Pool ( you must call this before 'new',
	//          if you want to reconfigure Pool. if you don't call
	//          it, then Pool works with default configuration )
	// Param  : nPoolSize - Size of Pool (Object Block Total count)
	//          bAllocNow - Virtual Allocation right now
	//          nObjSize - bAllocNow is true, then you must give Object size 
	//                     cos, i don't know object's size in this time )
	// Return : if bAllocNow is true, so pool try to alloc, but it fail
	//          then it return false.
	//-----------------------------------------------------------
	// Coder  Dated                    Desc
	// bro    2002-02-20
	//===========================================================
	static inline BOOL vmInitPool( DWORD dwPoolSize , BOOL bAllocNow = FALSE, DWORD dwObjSize = 0 )
	{
		ms_dwPoolSize = dwPoolSize;
		if( bAllocNow && dwObjSize > 0 )
		{
			ms_dwObjSize = dwObjSize;
			if( !AllocPool(ms_dwPoolSize,ms_dwObjSize) )
			{
				return FALSE;
			}
		}

		return TRUE;
	}
	
	//===========================================================
	// Name   : vmCleanUp
	// Desc   : you should put it on term code
	//          but, it's optional. cos all freed safely when 
	//          process terminate.
	// Param  : 
	// Return : 
	//-----------------------------------------------------------
	// Coder  Dated                    Desc
	// bro    2002-02-20
	//===========================================================
	static inline void vmCleanUp()
	{
		if( ms_pMemPool )
			VirtualFree( ms_pMemPool, DWORD(ms_dwPoolSize*ms_dwObjSize), MEM_RELEASE|MEM_DECOMMIT );
		DeleteCriticalSection( &ms_csLock );
	}

	//===========================================================
	// Name   : vmGetPoolInfo
	// Desc   : Get Pool information
	//          If you interest of pool memory usage statistics
	//          then you can use it for that.
	// Param  : pdwPoolSize - [out] Pool Object total count( Not bytes )
	//          pdwAllocObjCount - [out] Current allocated object count
	//          pdwObjSize - [out] one object bytes size.
	// Return : 
	//-----------------------------------------------------------
	// Coder  Dated                    Desc
	// bro    2002-02-20
	//===========================================================
	static inline BOOL vmGetPoolInfo( DWORD* pdwPoolSize, DWORD* pdwAllocObjCount, DWORD* pdwObjSize )
	{
		BOOL bRet = TRUE;
		if( !ms_pMemPool )
			bRet = FALSE;
		if( pdwPoolSize ) *pdwPoolSize = ms_dwPoolSize;
		if( pdwAllocObjCount ) *pdwAllocObjCount = ms_dwAllocObjCount;
		if( pdwObjSize ) *pdwObjSize = ms_dwObjSize;

		return bRet;
	}
	// memory block validation checker
	static inline BOOL vmIsBadPtr( void* p )
	{
		// is follow basic rule of pool block?
		if( p && p>=ms_pData && p<=ms_pData+(ms_dwPoolSize*ms_dwObjSize)&&
				((char*)p-ms_pData)%ms_dwObjSize == 0 )
		{
			// is really allocated in pool ?
			DWORD id = Addr2Id(p);
			return (ms_bsAllocSet.Get(id)==0);
		}
		return TRUE;
	}
	struct CSLock
	{
		CRITICAL_SECTION  cs;
		CSLock(){ InitializeCriticalSection(&cs); }
		~CSLock(){ DeleteCriticalSection(&cs); }
		void Lock(){ EnterCriticalSection(&cs); }
		void Unlock() { LeaveCriticalSection(&cs); }
	};
private:
	static CBitSet			ms_bsAllocSet;			// bitset for allocated blocks
	static DWORD			ms_dwSrtFree;			// freeblock start marker in circular queue
	static DWORD			ms_dwEndFree;			// freeblock end marker
	static BOOL				ms_bEmptyFree;			// state value for empry queue
	static BOOL				ms_bFullFree;			// state value for full queue
	
	static DWORD			ms_dwFreeQueueSize;
	static DWORD			ms_dwTotalSize;


	static CSLock	ms_csLock;
	static char*	ms_pMemPool;					// Virtual memory pool pointer
	static char*	ms_pData;						// real data pointer
	static DWORD	ms_dwPoolSize;					// Total Pool object counter
	static DWORD	ms_dwObjSize;					// one object size (bytes)
	static DWORD	ms_dwAllocObjCount;				// current allocated counts
	
	

	// translate address to block numer
	static inline DWORD	Addr2Id( void* p )
	{
		return DWORD((char*)p-ms_pData)/ms_dwObjSize;
	}
	// translate block number to address
	static inline void* Id2Addr( DWORD id )
	{
		return ms_pData+(ms_dwObjSize*id);
	}

	// add free block number to free-circular queue
	static inline BOOL InsertFree( DWORD id )
	{
		if( (ms_dwEndFree+1) % ms_dwFreeQueueSize == ms_dwSrtFree )
		{
			// OverFlow
			return FALSE;
		}
		// write newbie free block
		*((DWORD*)ms_pMemPool+ms_dwEndFree) = id;
		ms_dwEndFree = ++ms_dwEndFree % ms_dwFreeQueueSize;
		// free block bit set 
		ms_bsAllocSet.Set( id, 0 );

		return TRUE;
	}
	// pop free block from free-circular queue
	static inline DWORD PopFree()
	{
		if( ms_dwSrtFree == ms_dwEndFree )
		{
			// Underflow ( no block for use )
			return 0xFFFFFFFF;
		}

		// get free id
		DWORD id = *((DWORD*)ms_pMemPool+ms_dwSrtFree);
		// bit set it is used.
		ms_bsAllocSet.Set( id, 1 );
		
		// increment start free marker
		ms_dwSrtFree=(++ms_dwSrtFree)%ms_dwFreeQueueSize;
		return id;
	}

	static inline BOOL AllocPool(DWORD dwPoolSize, DWORD dwObjSize)
	{
		DWORD dwUsedBytes = ms_bsAllocSet.sCalcUsedBytes(dwPoolSize);
		DWORD dwFreeQueue = (dwPoolSize+1)*sizeof(DWORD);
		DWORD dwTotalSize = dwUsedBytes + dwFreeQueue + dwPoolSize*dwObjSize;

		ms_pMemPool = (char*)VirtualAlloc( NULL, dwTotalSize, 
							MEM_RESERVE|MEM_COMMIT|MEM_TOP_DOWN, 
							PAGE_READWRITE );
		if( !ms_pMemPool)
			return FALSE;
		ms_dwTotalSize = dwTotalSize;
		ms_dwFreeQueueSize = dwPoolSize+1;
		ms_pData = ms_pMemPool+dwUsedBytes+dwFreeQueue;

		// allocation bitset create
		if(!ms_bsAllocSet.Create( dwPoolSize, TRUE, TRUE, ms_pMemPool+dwFreeQueue,dwUsedBytes ) )
			return FALSE;
		
		// free circular queue init
		ms_dwSrtFree = 0;
		ms_dwEndFree = 0;
		ms_bEmptyFree = TRUE;
		ms_bFullFree = FALSE;
		for( DWORD i = 0 ; i < dwPoolSize; i++)
		{
			// all block is available when pool is created.
			InsertFree(i);
		}

		return TRUE;
	}
public:
	// DEBUG_NEW support function ( No support memory tracking for MFC )
	inline void* operator new(size_t nSize, LPCSTR lpszFileName, int nLine)
	{
		return operator new( nSize );
	}
	inline void operator delete(void* p, LPCSTR lpszFileName, int nLine)
	{
		operator delete( p );
	}

	// new operator override
	void* operator new( size_t size )
	{
		ASSERT( size > 0 );
		// pointer for newed free address in pool
		void* pNew = NULL;
		
		ms_csLock.Lock();


		//====================================================
		// if pool isn't init, then init
		if( !ms_pMemPool )
		{
			if( !ms_dwPoolSize ) ms_dwPoolSize = _dwPoolSizeT;
			ms_dwObjSize = size;
			if( !AllocPool(ms_dwPoolSize,ms_dwObjSize) )
			{
				ms_csLock.Unlock();
				return NULL;
			}
		}
		
		// get available block in pool
		DWORD id = PopFree();
		if( id == 0xFFFFFFFF )
		{
			return NULL;
		}
		pNew = Id2Addr(id);
		
		//====================================================
		if( pNew )
			ms_dwAllocObjCount++;
		else
			;//allocation fail!
		ms_csLock.Unlock();
		return pNew;
	}
	// free memory
	void operator delete( void* p )
	{
		ASSERT( p && 
				p>=ms_pData&&
				p<=ms_pData+(ms_dwPoolSize*ms_dwObjSize)&&
				((char*)p-ms_pData)%ms_dwObjSize == 0 );
				

		if( !p ) return;
		
		// lock pool
		ms_csLock.Lock();

		//====================================================
		// add to 'free-queue'for reusing this block 
		InsertFree( Addr2Id(p) );

		ms_dwAllocObjCount--;
		//====================================================
		
		// unlock
		ms_csLock.Unlock();
	}
};

// declaration static valuables
template <class T,DWORD F> CBitSet CVMemPool<T,F>::ms_bsAllocSet;
template <class T,DWORD F> DWORD CVMemPool<T,F>::ms_dwSrtFree;
template <class T,DWORD F> DWORD CVMemPool<T,F>::ms_dwEndFree;
template <class T,DWORD F> BOOL CVMemPool<T,F>::ms_bEmptyFree;
template <class T,DWORD F> BOOL CVMemPool<T,F>::ms_bFullFree;
template <class T,DWORD F> DWORD CVMemPool<T,F>::ms_dwTotalSize;
template <class T,DWORD F> DWORD CVMemPool<T,F>::ms_dwFreeQueueSize;
template <class T,DWORD F> char* CVMemPool<T,F>::ms_pData;

template <class T,DWORD F> CVMemPool<T,F>::CSLock CVMemPool<T,F>::ms_csLock;
template <class T,DWORD F> char*	CVMemPool<T,F>::ms_pMemPool = NULL;
template <class T,DWORD F> DWORD CVMemPool<T,F>::ms_dwObjSize;
template <class T,DWORD F> DWORD CVMemPool<T,F>::ms_dwAllocObjCount;
template <class T,DWORD F> DWORD CVMemPool<T,F>::ms_dwPoolSize;


#endif // !defined(AFX_VMEMPool_H__BD52675B_6C82_4CDE_8618_0141D7A4653F__INCLUDED_)
2011-11-16 19:23
0
游客
登录 | 注册 方可回帖
返回
//