This commit is contained in:
aixianling
2025-01-09 17:45:40 +08:00
commit 5c9f1dae4a
3482 changed files with 1146531 additions and 0 deletions

View File

@@ -0,0 +1,63 @@
#ifndef _ALIGN_ALLOCATOR_H_
#define _ALIGN_ALLOCATOR_H_
/************************************************************************
* 适用于小内存的频繁分配的场景,同时为了性能牺牲了部分内存空间
************************************************************************/
using namespace lock;
#define GetAlignIdx(t) (t % align_ == 0 ? (t / align_ - 1) : (t / align_))
class AlignAllocator : public BaseAllocator
{
struct FreeNode
{
FreeNode* next_;
int size_;
};
struct Header
{
FreeNode* first_;
int total_;
int free_;
Header()
{
total_ = free_ = 0;
first_ = NULL;
}
};
public:
AlignAllocator(const char* name, int max_size, int align);
virtual ~AlignAllocator();
public:
#ifndef _MEMORY_TRACE_
virtual void* AllocBuffer(size_t count);
virtual void* ReAllocBuffer(void* src, size_t count);
virtual void FreeBuffer(void* ptr);
#else
virtual void* _AllocBuffer(size_t count, const char*, int);
virtual void* _ReAllocBuffer(void* src, size_t newsize, const char* fn, int line);
virtual void _FreeBuffer(void* ptr, const char*, int);
#endif
void Init(int max_size, int align);
void GC();
void SetMultiThread(bool flag) { mult_thread_ = flag; }
void SetGCRest(int rest) { rest_ = rest; }
private:
int max_size_;
int align_;
Header* heads_;
int hdrCnt_;
int rest_;
// 支持加锁,可以多线程安全
bool mult_thread_;
Mutex buffer_lock_;
};
#endif //end _ALIGN_ALLOCATOR_H_

View File

@@ -0,0 +1,54 @@
#ifndef _BASE_ALLOCATOR_H_
#define _BASE_ALLOCATOR_H_
/************************************************************************
* 内存分配器的基类,其他分配器可继承其接口,实现不同的内存分配算法
*
*
/************************************************************************/
#include "memory_counter.hpp"
class BaseAllocator : public AllocatorCounterItem
{
public:
#ifndef _MEMORY_TRACE_
virtual void* AllocBuff(size_t count)
#else
#define AllocBuff(count_) _AllocBuff(count_,__FILE__, __LINE__)
#define FreeBuff(ptr) _FreeBuff(ptr, __FILE__, __LINE__)
virtual void* _AllocBuff(size_t count,const char* lpFile, int nLine)
#endif
{
void* result = malloc(count);
#ifdef _MEMORY_TRACE_
if (result != NULL)
{
used_count_ += count;
}
#endif
return result;
}
#ifndef _MEMORY_TRACE_
virtual void FreeBuff(void* ptr)
#else
virtual void _FreeBuff(void* ptr,const char* lpFile, int nLine)
#endif
{
if (ptr) free(ptr);
}
BaseAllocator(const char* namestr) : AllocatorCounterItem(namestr)
{
}
virtual ~BaseAllocator()
{
}
//public:
//#ifdef _MEMORY_TRACE_
// virtual int Log(char* buf, int num){ return sprintf(buf,"alloc total:%d,used:%d",alloc_total_,used_count); }
//#endif
};
#endif //end _BASE_ALLOCATOR_H_

View File

@@ -0,0 +1,23 @@
#ifndef _ALLOCDEF_H_
#define _ALLOCDEF_H_
#include "os_def.h"
/************************************************************************
* 内存分配的头文件定义
*
*
************************************************************************/
#ifdef _MEMORY_TRACE_
typedef struct
{
size_t buff_size_;
struct
{
const char* fn_; //申请内存块的代码位置,用于调试
int line_;
} al_, fl_;
bool using_flag_;
} AllocBuffHead;
#endif
#endif //end _ALLOCDEF_H_

View File

@@ -0,0 +1,90 @@
#ifndef _BASE_ALLOCATOR_H_
#define _BASE_ALLOCATOR_H_
/************************************************************************
* 内存分配器的基类,其他分配器可继承其接口,实现不同的内存分配算法
* 这个基类实现的内存分配就是直接用crt分配内存
************************************************************************/
#include "os_def.h"
#include "memory_counter.hpp"
#ifdef _MEMORY_TRACE_
#define AllocBuffer(count_) _AllocBuffer(count_,__FILE__, __LINE__)
#define ReAllocBuffer(src,count_) _ReAllocBuffer(src,count_,__FILE__, __LINE__)
#define FreeBuffer(ptr) _FreeBuffer(ptr, __FILE__, __LINE__)
#endif
class BaseAllocator : public AllocatorCounterItem
{
public:
#ifndef _MEMORY_TRACE_
virtual void* AllocBuffer(size_t count)
#else
virtual void* _AllocBuffer(size_t count, const char*, int)
#endif
{
size_t* result = (size_t*)malloc(count + sizeof(size_t));
#ifdef _MEMORY_TRACE_
if (result != NULL)
{
alloc_total_ += count;
*result = count;
}
#endif
return (void*)(result + 1);
}
#ifndef _MEMORY_TRACE_
virtual void* ReAllocBuffer(void* src, size_t count)
#else
virtual void* _ReAllocBuffer(void* src, size_t count, const char*, int)
#endif
{
#ifdef _MEMORY_TRACE_
if (src)
{
size_t old = *((size_t*)src - 1);
alloc_total_ -= old;
src = (void*)((size_t*)src - 1);
}
alloc_total_ += count; // 注意是size_t类型
#endif
size_t* result = (size_t*)realloc(src, count + sizeof(size_t));
*result = count;
return (void*)(result + 1);
}
#ifndef _MEMORY_TRACE_
virtual void FreeBuffer(void* ptr)
#else
virtual void _FreeBuffer(void* ptr, const char*, int)
#endif
{
if (!ptr) return;
#ifdef _MEMORY_TRACE_
size_t old = *((size_t*)ptr - 1);
alloc_total_ -= old;
#endif
free((size_t*)ptr - 1);
}
BaseAllocator(const char* namestr) : AllocatorCounterItem(namestr)
{
}
virtual ~BaseAllocator()
{
}
void SetMultiThread(bool){}
void GC()
{
}
};
#endif //end _BASE_ALLOCATOR_H_

View File

@@ -0,0 +1,94 @@
#ifndef _MSG_ALLOCATOR_H_
#define _MSG_ALLOCATOR_H_
#include "os_def.h"
#include "x_tick.h"
#include "base_allocator.hpp"
#include "x_lock.h"
class BaseAllocator;
using namespace tick64;
using namespace lock;
class BufferAllocator: public BaseAllocator
{
public:
static const unsigned int SmallBufferSize = 64; //小块内存块大小
static const unsigned int MiddleBufferSize = 256; //中等内存块大小
static const unsigned int LargeBufferSize = 1024; //大块内存块大小
#pragma pack(push, 1)
typedef struct tagBuffer
{
size_t size_; //内存数据段大小
tagBuffer* prev_buffer_;//指向上一个内存块的指针
int64_t free_tick_; //即将被销毁的时间
#ifdef _MEMORY_TRACE_
tagBuffer* next_buffer_;//指向上下个内存块的指针,用于调试
struct
{
const char* fn_; //申请内存块的代码位置,用于调试
int line_;
} al, fl;
bool used_flag_; //是否使用的标记
#endif
} BUFFER, *PBUFFER;
#pragma pack(pop)
struct BufferStatic
{
size_t alloc_size_;
size_t free_size_;
};
typedef struct tagAllocatorMemoryInfo
{
BufferStatic SmallBuffer;
BufferStatic MiddleBuffer;
BufferStatic LargeBuffer;
BufferStatic SuperBuffer;
} ALLOCATOR_MEMORY_INFO;
private:
Mutex buffer_lock_; //内存块申请锁
PBUFFER last_small_buffer_; //指向最后一个空闲的小型内存块的指针
PBUFFER last_middle_buffer_; //指向最后一个空闲的中型内存块的指针
PBUFFER last_large_buffer_; //指向最后一个空闲的大型内存块的指针
PBUFFER last_super_buffer_; //指向最后一个空闲的超级内存块的指针
#ifdef _MEMORY_TRACE_
PBUFFER last_alloced_buffer_; //指向最后一个被申请的内存块
#endif
size_t alloced_small_size_; //已被申请的小型内存块大小
size_t alloced_middle_size_; //已被申请的中型内存块大小
size_t alloced_large_size_; //已被申请的大型内存块大小
size_t alloced_super_size_; //已被申请的超级内存块大小
size_t freed_small_size_; //已被释放的小型内存块大小
size_t freed_middle_size_; //已被释放的中型内存块大小
size_t freed_large_size_; //已被释放的大型内存块大小
size_t freed_super_size_; //已被释放的超级内存块大小
bool mult_thread_;
public:
BufferAllocator(const char* namestr);
~BufferAllocator();
#ifndef _MEMORY_TRACE_
void* AllocBuffer(size_t size);
void* ReAllocBuffer(void* ptr, size_t new_size);
void FreeBuffer(void* ptr);
#else
void* _AllocBuffer(size_t size, const char* fn, int line);
void* _ReAllocBuffer(void* ptr, size_t new_size, const char* fn, int line);
void _FreeBuffer(void* ptr, const char* fn, int line);
#endif
void GetMemoryInfo(BufferAllocator::ALLOCATOR_MEMORY_INFO* pMemoryInfo);
void CheckFreeBuffers();
void SetMultiThread(bool flag);
void GC();
};
#endif

View File

@@ -0,0 +1,463 @@
#ifndef _HANDLE_MGR_H_
#define _HANDLE_MGR_H_
#include "os_def.h"
#include <stdint.h>
namespace memory
{
//template <typename TAG>
class Handle
{
public:
union
{
struct
{
unsigned int index_ : 21; // index into resource array 资源数组的索引
unsigned int magic_ : 11; // magic number to check 需要检查的魔术数
};
unsigned int handle_;
};
public:
const static int MAX_INDEX = (1 << 21) - 1;
const static int MAX_MAGIC = (1 << 11) - 1;
Handle(void) : handle_(0) { }
Handle(unsigned int handle)
{
handle_ = handle ; //
}
void Init(unsigned int index)
{
assert(index <= (unsigned int)MAX_INDEX);
index_ = index;
magic_ = wrand(MAX_MAGIC) + 1; //magic_不能等于0否则可能handle==0
}
inline void Update()
{
++magic_;
if (handle_ == 0) ++magic_;
}
inline bool IsNull(void) const
{
return (!handle_);
}
inline unsigned int GetIndex(void) const
{
return (index_);
}
inline unsigned int GetHandle(void) const
{
return (handle_);
}
inline static unsigned int GetMaxIndex()
{
return MAX_INDEX;
}
operator unsigned int (void) const
{
return (handle_);
}
inline Handle& operator = (const unsigned int h)
{
handle_ = h;
return *this;
}
};
//一个64位的handle值支持更大的索引值和魔术数应用到需要分配更大内存的地方
//template <typename TAG>
class Handle64
{
public:
union
{
struct
{
unsigned int index_ : 32; // index into resource array 资源数组的索引
unsigned short magic_ : 16; // magic number to check 需要检查的魔术数
unsigned short rev_ : 16;
};
int64_t handle_;
};
public:
Handle64(void) : handle_(0) { }
Handle64(int64_t nHandle)
{
handle_ = nHandle ; //
}
void Init(unsigned int index)
{
assert(index <= GetMaxIndex());
index_ = index;
magic_ = wrand(0xffff) + 1;
}
inline void Update()
{
++magic_;
if (handle_ == 0) ++magic_;
}
inline bool IsNull(void) const
{
return (!handle_);
}
inline unsigned int GetIndex(void) const
{
return (index_);
}
inline int64_t GetHandle(void) const
{
return (handle_);
}
inline static unsigned GetMaxIndex()
{
return 0xffffffff ;
}
inline operator int64_t (void) const
{
return (handle_);
}
inline Handle64& operator = (const int64_t v)
{
handle_ = v;
return *this;
}
inline Handle64& operator = (const Handle64 v)
{
handle_ = v.handle_;
return *this;
}
};
template <typename DATA, typename HDL, int ONE_TIME_COUNT = 1024>
class HandleMgr :
public AllocatorCounterItem
{
public:
typedef AllocatorCounterItem Inherited;
struct tagHandle
{
HDL handle_;
bool using_flag_;
};
private:
const static int BUFF_SIZE = sizeof(DATA) + sizeof(tagHandle);
struct DataBlock
{
DataBlock* prev_;
}* data_block_;
public:
#ifndef _MEMORY_TRACE_
DATA* AllocHandle(HDL& handle)
#else
#define AllocHandle(handle) _AllocHandle(handle,__FILE__, __LINE__)
#define Free(ptr) _Free(ptr, __FILE__, __LINE__)
DATA* _AllocHandle(HDL& handle, const char* file_name, int line)
#endif
{
void* result = NULL;
int count = free_list_.count();
if (count <= 0)
{
count = all_list_.size() <= 0 ? ONE_TIME_COUNT : all_list_.size() * 2; //每次double
if (unsigned(all_list_.size() + count) > HDL::GetMaxIndex())
{
count = HDL::GetMaxIndex() - all_list_.size();
if (count <= 0)
{
return NULL;
}
}
#ifndef _MEMORY_TRACE_
size_t allocsize = sizeof(DataBlock) + BUFF_SIZE * count;
#else
size_t allocsize = sizeof(DataBlock) + (BUFF_SIZE + sizeof(AllocBuffHead)) * count;
#endif
DataBlock* block_ptr = (DataBlock*)malloc(allocsize);
#ifdef _MEMORY_TRACE_
alloc_total_ += allocsize;
#endif
//将对象指针全部添加到空闲列表中
result = (void*)(block_ptr + 1);
int max_size = all_list_.size() + count;
if (free_list_.max_size() < max_size)
free_list_.reserve(max_size);
int index = all_list_.size();
void** list = free_list_;
for (int i = 0; i < count; ++i)
{
tagHandle* hdl_ptr = NULL;
list[i] = result;
#ifdef _MEMORY_TRACE_
AllocBuffHead* hdr = (AllocBuffHead*)result;
hdr->using_flag_ = false;
hdr->buff_size_ = BUFF_SIZE;
hdl_ptr = (tagHandle*)((char*)result + sizeof(AllocBuffHead));
result = (void*)((char*)result + BUFF_SIZE + sizeof(AllocBuffHead));
#else
hdl_ptr = (tagHandle*)result;
result = (void*)((char*)result + BUFF_SIZE);
#endif
hdl_ptr->handle_ = 0;
hdl_ptr->handle_.Init(index);
hdl_ptr->using_flag_ = false;
index++;
}
all_list_.addArray(free_list_, count); //已经分配的记录下
//标记上内存块的上一个内存块
block_ptr->prev_ = data_block_;
data_block_ = block_ptr;
}
//返回列表中的最后一个对象
count--;
result = free_list_[count];
free_list_.trunc(count);
#ifdef _MEMORY_TRACE_
used_count_ += BUFF_SIZE;
#endif
#ifdef _MEMORY_TRACE_
AllocBuffHead* hdr = (AllocBuffHead*)result;
#ifdef _MSC_VER
assert(hdr->using_flag_ == false);
#endif
hdr->using_flag_ = true;
hdr->al_.fn_ = file_name;
hdr->al_.line_ = line;
result = hdr + 1;
#endif
tagHandle* hdl_ptr = (tagHandle*)result;
hdl_ptr->handle_.Update();//index不变改magicnum
result = (void*)((char*)result + sizeof(tagHandle));
DATA* pd = (DATA*)result;
new(pd)DATA(); //构造函数
handle = hdl_ptr->handle_;
hdl_ptr->using_flag_ = true;
return pd;
}
#ifndef _MEMORY_TRACE_
void Free(DATA* ptr)
#else
void _Free(DATA* ptr, const char* file_name, int line)
#endif
{
if (ptr == NULL) return;
tagHandle* hdl_ptr = (tagHandle*)ptr;
hdl_ptr--;
//检查是否合法
if (GetPtr(hdl_ptr->handle_) == NULL)
{
return;
}
#ifndef _MEMORY_TRACE_
SavePtr(hdl_ptr);
#else
SavePtr(hdl_ptr, file_name, line);
#endif
}
#ifndef _MEMORY_TRACE_
void Free(HDL handle)
#else
void _Free(HDL handle, const char* file_name, int line)
#endif
{
tagHandle* hdl_ptr = (tagHandle*)GetPtr(handle);
if (hdl_ptr == NULL)
{
return;
}
hdl_ptr--;
#ifndef _MEMORY_TRACE_
SavePtr(hdl_ptr);
#else
SavePtr(hdl_ptr, file_name, line);
#endif
}
//根据handle获取指针
DATA* GetPtr(HDL handle)
{
//验证下这个指针是不是这里分配出去的
int index = handle.GetIndex();
if (index < 0 || index >= all_list_.size())
{
return NULL;
}
void* save_ptr = all_list_[index];
#ifdef _MEMORY_TRACE_
tagHandle* hdl_ptr = (tagHandle*)((char*)save_ptr + sizeof(AllocBuffHead));
#else
tagHandle* hdl_ptr = (tagHandle*)save_ptr;
#endif
HDL& h = hdl_ptr->handle_;
if (h.index_ != handle.index_ || h.magic_ != handle.magic_ || !hdl_ptr->using_flag_) //handle根本是不合法的
{
return NULL;
}
return (DATA*)((char*)hdl_ptr + sizeof(tagHandle));
}
bool ReNew(HDL& handle)
{
// 检查有效性
if (!GetPtr(handle)) return false;
handle.Update();
int index = handle.GetIndex();
void* save_ptr = all_list_[index];
#ifdef _MEMORY_TRACE_
tagHandle* hdl_ptr = (tagHandle*)((char*)save_ptr + sizeof(AllocBuffHead));
#else
tagHandle* hdl_ptr = (tagHandle*)save_ptr;
#endif
hdl_ptr->handle_ = handle; // 更新成新的handle
return true;
}
HandleMgr(const char* namestr)
: Inherited(namestr)
{
data_block_ = NULL;
}
~HandleMgr()
{
#ifdef _MEMORY_TRACE_
for (int i = 0; i < all_list_.size(); i++)
{
AllocBuffHead* hdr = (AllocBuffHead*)(all_list_[i]);
if (hdr->using_flag_)
{
char err[1024];
SNPRINTFA(err, sizeof(err) - 1, " %s check memory leaks(size:%d)alloc%s(%d)\n",
__FUNCTION__, (int)hdr->buff_size_, hdr->al_.fn_, hdr->al_.line_);
OutputWatchFile(err, "err.log");
}
#ifdef _MSC_VER
assert(hdr->using_flag_ == false);//内存泄露了
#endif
}
#endif
DataBlock* block_ptr, *prev;
block_ptr = data_block_;
int block_count = 0;
while (block_ptr)
{
prev = block_ptr->prev_;
free(block_ptr);
block_ptr = prev;
block_count++;
}
data_block_ = NULL;
#ifdef _MEMORY_TRACE_
size_t free_size = free_list_.count() * (BUFF_SIZE + sizeof(AllocBuffHead)) + block_count * sizeof(DataBlock);
if (free_size != alloc_total_)
{
char err[1024];
SNPRINTFA(err, sizeof(err) - 1, "%s:%s:%d memory error,free size:%lld, alloc_size:%lld\n",
__FUNCTION__, __FILE__, __LINE__, (long long int)free_size, (long long int)alloc_total_);
OutputWatchFile(err, "err.log");
}
#ifdef _MSC_VER
assert(free_size == alloc_total_); //简单的检查是否内存泄露
#endif
#else
assert(free_list_.count()*BUFF_SIZE + block_count * sizeof(DataBlock) == alloc_total_); //简单的检查是否内存泄露
#endif
}
//public:
//#ifdef _MEMORY_TRACE_
// virtual int Log(char* buf, int num){ return sprintf(buf,"alloc total:%d,used:%d",alloc_total_,used_count); }
//#endif
private:
#ifndef _MEMORY_TRACE_
void SavePtr(tagHandle* hdl_ptr)
#else
void SavePtr(tagHandle* hdl_ptr, const char* file_name, int line)
#endif
{
//改掉magicnum
hdl_ptr->using_flag_ = false;
hdl_ptr->handle_.Update();
void* save_ptr = (void*) hdl_ptr;
#ifdef _MEMORY_TRACE_
AllocBuffHead* hdr = (AllocBuffHead*)save_ptr;
hdr--;
if (!hdr->using_flag_)
{
printf(" %sFree the buff that had be release before(size:%d)alloc%s(%d)free%s(%d)\n",
__FUNCTION__, (int)hdr->buff_size_, hdr->al_.fn_, hdr->al_.line_,
hdr->fl_.fn_, hdr->fl_.line_);
}
#ifdef _MSC_VER
assert(hdr->using_flag_);//检查有没有重复释放
#endif
hdr->using_flag_ = false;
hdr->fl_.fn_ = file_name;
hdr->fl_.line_ = line;
save_ptr = hdr;
#endif
DATA* data_ptr = (DATA*)(++hdl_ptr);
data_ptr->~DATA();
free_list_.add(save_ptr);
#ifdef _MEMORY_TRACE_
used_count_ -= BUFF_SIZE;
#endif
}
protected:
container::Vector<void*> free_list_;
container::Vector<void*> all_list_;//所有分配的内存都会在这里记录
};
};
#endif

View File

@@ -0,0 +1,172 @@
#ifndef _BUFF_ALLOCATOR_H_
#define _BUFF_ALLOCATOR_H_
/************************************************************************
* 一次性的内存分配器
* 适用于一次分配内存后,直到程序结束才释放内存的地方,如配置文件的读取
* 用这个分配器的好处是:不提供释放内存的函数,因此不需要一个个内存手工释放,
* 而是由分配器一次释放
************************************************************************/
#include "os_def.h"
#include "memory_counter.hpp"
template <typename T, int ONE_TIME_COUNT = 1024>
class MemoryContainer : public AllocatorCounterItem
{
public:
typedef AllocatorCounterItem Inherited;
//内存块描述结构,用于查询内存块信息
struct DataBlockDesc
{
const char* addr;//内存块指针地址
size_t block_size; //内存块大小
};
private:
//内存块链表节点
struct DataBlock
{
T* free_ptr; //指向空闲的对象
T* end_ptr; //指向对象内存块的结束
DataBlock* prev;
} *data_block_;
public:
#ifndef _MEMORY_TRACE_
T* AllocBuffer(size_t count)
#else
T* _AllocBuffer(size_t count, const char*, int)
#endif
{
T* result;
DataBlock *block_ptr = data_block_;
//尝试从当前内存块中申请nCount的对象如果内存块中没有足够的对象则向之前的内存块中查找是否具有足够的空闲对象
if ( !block_ptr || size_t(block_ptr->end_ptr - block_ptr->free_ptr) < count )
{
//向之前的内存块中查找是否具有足够的空闲对象
while (block_ptr && (block_ptr = block_ptr->prev))
{
if ( size_t(block_ptr->end_ptr - block_ptr->free_ptr) >= count )
break;
}
//如果所有内存块中都没有足够的对象则申请新内存块
if ( block_ptr == NULL )
{
size_t alloc_count = __max(count, ONE_TIME_COUNT);
block_ptr = (DataBlock*)malloc(sizeof(DataBlock) + sizeof(T) * alloc_count);
memset(block_ptr, 0, sizeof(DataBlock) + sizeof(T) * alloc_count);
#ifdef _MEMORY_TRACE_
alloc_total_ += alloc_count;
#endif
block_ptr->free_ptr = (T*)(block_ptr + 1);
block_ptr->end_ptr = block_ptr->free_ptr + alloc_count;
block_ptr->prev = data_block_;
data_block_ = block_ptr;
}
}
//返回对象指针
result = block_ptr->free_ptr;
block_ptr->free_ptr += count;
#ifdef _MEMORY_TRACE_
used_count_ += count;
#endif
return result;
}
void _FreeBuffer()
{
DataBlock *block_ptr, *prev;
block_ptr = data_block_;
while (block_ptr)
{
prev = block_ptr->prev;
free(block_ptr);
block_ptr = prev;
}
data_block_ = NULL;
}
//获取内存块数量
inline int blockCount() const
{
int result = 0;
DataBlock *block_ptr = data_block_;
while (block_ptr)
{
result++;
block_ptr = block_ptr->prev;
}
return result;
}
/*
* Comments: 枚举内存块描述信息
* Param LPCVOID lpEnumKey: 上次枚举的返回值作为枚举下一个的依据第一次枚举此值必须为NULL。
* Param DataBlockDesc & desc: 用于保存内存块描述的对象
* @Return LPCVOID: 返回一个内存块枚举key指针便于进行下次枚举。如果返回值为NULL则表示枚举结束
*
* ★★注意★★:枚举内存块描述的操作是倒叙进行的,第一个被枚举的内存块描述为左后一个内存块的描述!
*
* ★★示例代码★★:-------------------------------------------------
* LPCVOID lpEnumKey = NULL;
* BuffAllocator<T>::DataBlockDesc desc;
* while (lpEnumKey = allocator.enumBlockDesc(lpEnumKey, desc))
* {
* printf("Memory Block Info { Address = %X, Size = %u }",
* desc.lpBaseAddress, desc.dwBlockSize);
* }
* --------------------------------------------------------------
*/
inline void* enumBlockDesc(void* enum_key, DataBlockDesc &desc) const
{
DataBlock *block_ptr = (DataBlock*)enum_key;
if (!block_ptr)
block_ptr = data_block_;
else block_ptr = block_ptr->prev;
if (block_ptr)
{
desc.addr = ((const char*)block_ptr) + sizeof(*block_ptr);
desc.block_size = block_ptr->end_ptr - desc.addr;
return block_ptr;
}
return NULL;
}
MemoryContainer(const char* namestr) : Inherited(namestr)
{
data_block_ = NULL;
}
virtual ~MemoryContainer()
{
DataBlock *block_ptr, *prev;
block_ptr = data_block_;
while (block_ptr)
{
prev = block_ptr->prev;
free(block_ptr);
block_ptr = prev;
}
data_block_ = NULL;
MemoryCounter::getSingleton().unregist((AllocatorCounterItem*)this);
}
inline MemoryContainer& operator = (const MemoryContainer &rhs)
{
Inherited::operator=(rhs);
data_block_ = rhs.data_block_;
return *this;
}
//public:
//#ifdef _MEMORY_TRACE_
// virtual int Log(char* buf, int num){ return sprintf(buf,"alloc total:%d,used:%d",alloc_total_,used_count); }
//#endif
private:
MemoryContainer(const MemoryContainer &rhs);
};
#endif //end _BUFF_ALLOCATOR_H_

View File

@@ -0,0 +1,245 @@
#ifndef _MEMORY_COUNTER_H_
#define _MEMORY_COUNTER_H_
/************************************************************************
* 内存分配统计
* 每个用于内存分配的类最好都继承这个,并实现接口,好方便内存使用量的统计
* 可通过宏定义_MEMORY_TRACE_ 开关
***********************************************************************/
#include "os_def.h"
#include "share_util.h"
#include <vector>
#ifdef _MEMORY_TRACE_
template <typename T, int ONE_TIME_NUM = 16>
class MemoryItemList
{
protected:
T* data_ptr_;
int max_size_;
int count_;
public:
MemoryItemList()
{
data_ptr_ = NULL;
max_size_ = 0;
count_ = 0;
}
virtual ~MemoryItemList()
{
empty();
}
inline int count() const
{
return count_;
}
int add(const T& data)
{
if (count_ >= max_size_)
reserve((max_size_ > 0) ? max_size_ * 2 : ONE_TIME_NUM);
memcpy(data_ptr_ + count_, &data, sizeof(data));
count_++;
return count_ - 1;
}
void remove(const int index)
{
assert(index > -1 && index < count_);
remove(index, 1);
}
void remove(const int index, const int count)
{
assert(index + count <= count_);
if (count > 0)
{
memmove(data_ptr_ + index, data_ptr_ + index + count, sizeof(data_ptr_[0]) * (count_ - index - count));
count_ -= count;
}
}
virtual void empty()
{
clear();
max_size_ = 0;
if (data_ptr_)
{
free(data_ptr_);
data_ptr_ = NULL;
}
}
inline void clear()
{
count_ = 0;
}
virtual void reserve(int count)
{
if (count > count_ && count != max_size_)
{
max_size_ = count;
data_ptr_ = (T*)realloc(data_ptr_, sizeof(T) * count);
}
}
inline operator T* () const
{
return data_ptr_;
}
};
class MemoryCounter;
class AllocatorCounterItem
{
friend class MemoryCounter;
public:
enum
{
MAX_NAME_LENGTH = 32, // 最大描述字符串长度
};
AllocatorCounterItem(const char* namestr);
virtual ~AllocatorCounterItem();
const char* GetName()
{
return name_;
}
virtual int Log(char* buf, int num)
{
const char* fmt = "%s, alloc total:%llu, used:%llu %s";
const char* tip = GetTip(alloc_total_, used_count_);
return SNPRINTFA(buf, num, fmt, name_, alloc_total_, used_count_, tip);
}
size_t GetAllocCount()
{
return alloc_total_;
}
const char* GetTip(size_t s1, size_t s2 = 0)
{
const char* tip = "";
if (s1 > largeCount || s2 > largeCount)
{
tip = "*****";
}
else if (s1 > midCount || s2 > midCount)
{
tip = "**";
}
return tip;
}
public:
static const size_t largeCount = 100 * 1024 * 1024;
static const size_t midCount = 10 * 1024 * 1024;
protected:
size_t alloc_total_; //分配的总数
size_t free_count_; //空闲
size_t used_count_; //正在使用的内存量
char name_[MAX_NAME_LENGTH]; //
};
class SimpleAllocCounter : public AllocatorCounterItem
{
static const int MAX_COUNTER = 8;
public:
SimpleAllocCounter(const char* name) : AllocatorCounterItem(name)
{
memset(counter_, 0, sizeof(counter_));
}
size_t counter(size_t s, int idx)
{
assert(idx >= 0 && idx < MAX_COUNTER);
counter_[idx] += s;
alloc_total_ += s;
return counter_[idx];
}
virtual int Log(char* buf, int num)
{
const char* fmt = "%d, total:%llu %s\r\n";
int ret = 0;
for (int i = 0; i < MAX_COUNTER; i++)
{
size_t c = counter_[i];
if (c <= 0) continue;
const char* tip = GetTip(c);
ret += SNPRINTFA(buf + ret, num - ret, fmt, i, c, tip);
}
return ret;
}
private:
size_t counter_[MAX_COUNTER];
};
class MemoryCounter
{
public:
MemoryCounter();
static MemoryCounter& getSingleton()
{
static MemoryCounter mgr;
return mgr;
}
~MemoryCounter();
void clear()
{
allocator_list.clear();
allocator_list.empty();
}
/*
* Comments:添加一个统计项
* @Return void:
*/
void regist(AllocatorCounterItem* item);
/*
* Comments: 移除一个统计项
* Param CSingleObjectAllocatorStat * stat:
* @Return void:
*/
void unregist(AllocatorCounterItem* item);
/*
* Comments: 统计信息到日志
* @Return void:
*/
void logToFile();
private:
MemoryItemList<AllocatorCounterItem*, 2048> allocator_list;
};
#else //ifdef _MEMORY_TRACE_
class AllocatorCounterItem
{
public:
AllocatorCounterItem(const char* namestr)
{
}
};
#endif //ifdef _MEMORY_TRACE_
#endif //end _ONCE_ALLOCATOR_H_

View File

@@ -0,0 +1,213 @@
#ifndef _MEMPOOL_H_
#define _MEMPOOL_H_
/************************************************************************
* 内存分配器,只分配固定大小的内存,适用于频繁创建实例的类,结构体之类
************************************************************************/
#include "os_def.h"
#include "container/vector.h"
#include "memory_counter.hpp"
#include "allocdef.h"
template <int BUFF_SIZE, int ONE_TIME_COUNT = 1024>
class MemPool :
public AllocatorCounterItem
{
public:
typedef AllocatorCounterItem Inherited;
private:
struct DataBlock
{
DataBlock* prev_;
}* data_block_;
public:
#ifndef _MEMORY_TRACE_
void* Alloc()
#else
#define Alloc() _Alloc(__FILE__, __LINE__)
#define Free(ptr) _Free(ptr, __FILE__, __LINE__)
void* _Alloc(const char* file_name, int line)
#endif
{
void* result;
int count = free_list_.count();
if (count <= 0)
{
count = all_size_ > 0 ? all_size_ * 2 : ONE_TIME_COUNT; // 每次double
all_size_ += count;
#ifndef _MEMORY_TRACE_
size_t allocsize = sizeof(DataBlock) + BUFF_SIZE * count;
#else
size_t allocsize = sizeof(DataBlock) + (BUFF_SIZE + sizeof(AllocBuffHead)) * count;
#endif
DataBlock* block_ptr = (DataBlock*)malloc(allocsize);
#ifdef _MEMORY_TRACE_
alloc_total_ += allocsize;
#endif
//将对象指针全部添加到空闲列表中
result = (void*)(block_ptr + 1);
if (free_list_.max_size() < all_size_)
free_list_.reserve(all_size_);
void** list = free_list_;
for (int i = 0; i < count; ++i)
{
list[i] = result;
#ifdef _MEMORY_TRACE_
AllocBuffHead* hdr = (AllocBuffHead*)result;
hdr->using_flag_ = false;
hdr->buff_size_ = BUFF_SIZE;
result = (void*)((char*)result + BUFF_SIZE + sizeof(AllocBuffHead));
#else
result = (void*)((char*)result + BUFF_SIZE);
#endif
}
#ifdef _MEMORY_TRACE_
all_list_.addArray(free_list_, count);//已经分配的记录下
#endif
//标记上内存块的上一个内存块
block_ptr->prev_ = data_block_;
data_block_ = block_ptr;
}
//返回列表中的最后一个对象
count--;
result = free_list_[count];
free_list_.trunc(count);
#ifdef _MEMORY_TRACE_
used_count_ += BUFF_SIZE;
#endif
#ifdef _MEMORY_TRACE_
AllocBuffHead* hdr = (AllocBuffHead*)result;
#ifdef _MSC_VER
assert(hdr->using_flag_ == false); // 如果触发这个assert这个是有严重的bug这里先规避
#endif
hdr->using_flag_ = true;
hdr->al_.fn_ = file_name;
hdr->al_.line_ = line;
result = hdr + 1;
#endif
return result;
}
#ifndef _MEMORY_TRACE_
void Free(void* ptr)
#else
void _Free(void* ptr, const char* file_name, int line)
#endif
{
if (ptr == NULL) return;
#ifdef _MEMORY_TRACE_
AllocBuffHead* hdr = (AllocBuffHead*)ptr;
hdr--;
if (!hdr->using_flag_)
{
char err[1024];
SNPRINTFA(err, sizeof(err) - 1, " %s Free the buff that had be release before(size:%d),alloc%s(%d),free%s(%d),now:%s(%d)\n",
__FUNCTION__, (int)hdr->buff_size_, hdr->al_.fn_, hdr->al_.line_,
hdr->fl_.fn_, hdr->fl_.line_, file_name, line);
OutputWatchFile(err, "err.log");
#ifdef _MSC_VER
// 这个是有严重的bug这里先规避,直接return
assert(false);
#endif
return;
}
#ifdef _MSC_VER
assert(hdr->using_flag_);//检查有没有重复释放
#endif
hdr->using_flag_ = false;
hdr->fl_.fn_ = file_name;
hdr->fl_.line_ = line;
ptr = hdr;
#endif
free_list_.add(ptr);
#ifdef _MEMORY_TRACE_
used_count_ -= BUFF_SIZE;
#endif
}
MemPool(const char* namestr)
: Inherited(namestr)
{
data_block_ = NULL;
all_size_ = 0;
}
~MemPool()
{
#ifdef _MEMORY_TRACE_
for (int i = 0; i < all_list_.size(); i++)
{
AllocBuffHead* hdr = (AllocBuffHead*)(all_list_[i]);
if (hdr->using_flag_)
{
char err[1024];
SNPRINTFA(err, sizeof(err) - 1, " %scheck memory leaks(size:%d),alloc%s(%d)\n",
__FUNCTION__, (int)hdr->buff_size_, hdr->al_.fn_, hdr->al_.line_);
OutputWatchFile(err, "err.log");
}
#ifdef _MSC_VER
assert(hdr->using_flag_ == false);//内存泄露了
#endif
}
#endif
DataBlock* block_ptr, *prev;
block_ptr = data_block_;
int block_count = 0;
while (block_ptr)
{
prev = block_ptr->prev_;
free(block_ptr);
block_ptr = prev;
block_count++;
}
data_block_ = NULL;
#ifdef _MEMORY_TRACE_
size_t free_size = free_list_.count() * (BUFF_SIZE + sizeof(AllocBuffHead)) + block_count * sizeof(DataBlock);
if (free_size != alloc_total_)
{
char err[1024];
SNPRINTFA(err, sizeof(err) - 1, "%s:%s:%d memory error,free size:%lld, alloc_size:%lld\n",
__FUNCTION__, __FILE__, __LINE__, (long long int)free_size, (long long int)alloc_total_);
OutputWatchFile(err, "err.log");
}
#ifdef _MSC_VER
assert(free_list_.count() * (BUFF_SIZE + sizeof(AllocBuffHead)) + block_count * sizeof(DataBlock) == alloc_total_); //简单的检查是否内存泄露
#endif
#else
//assert(free_list_.count()*BUFF_SIZE+block_count*sizeof(DataBlock) == alloc_total_);//简单的检查是否内存泄露
#endif
}
//public:
//#ifdef _MEMORY_TRACE_
// virtual int Log(char* buf, int num){ return sprintf(buf,"alloc total:%d,used:%d",alloc_total_,used_count); }
//#endif
protected:
container::Vector<void*> free_list_;
int all_size_;
#ifdef _MEMORY_TRACE_
container::Vector<void*> all_list_;//所有分配的内存都会在这里记录
#endif
};
#endif //end _MEMPOOL_H_

View File

@@ -0,0 +1,55 @@
#ifndef _OJBPOOL_H_
#define _OJBPOOL_H_
/************************************************************************
* 内存分配器,只分配固定大小的类和结构体之类,
* 和mempool的区别是会自动执行构造函数和析构函数
************************************************************************/
#include "os_def.h"
#include "mempool.hpp"
template <typename T, int ONE_TIME_COUNT = 1024>
class ObjPool :
public MemPool<sizeof(T), ONE_TIME_COUNT>
{
typedef MemPool<sizeof(T), ONE_TIME_COUNT> Inherited;
public:
ObjPool(const char* namestr)
:Inherited(namestr)
{
}
#ifndef _MEMORY_TRACE_
T* Alloc()
{
T* result = (T*)Inherited::Alloc();
#else
T* _Alloc(const char* fn, int line)
{
T* result = (T*)Inherited::_Alloc(fn, line);
#endif
new(result)T();
return result;
}
#ifndef _MEMORY_TRACE_
void Free(T* ptr)
{
if (ptr == NULL) return;
ptr->~T();
Inherited::Free(ptr);
}
#else
void _Free(T* ptr, const char* fn, int line)
{
if (ptr == NULL) return;
ptr->~T();
Inherited::_Free(ptr, fn, line);
}
#endif
};
#endif