我写的内存管理类,高手请指点一下

vc_hunter 2006-02-06 06:20:41
/*以前去过家公司面试,有道题是:写一个内存管理类,所有的内存分配都通过类接口来实现。当时有点蒙,没做出来,我偶尔重载new和delete来扩展一些功能。用类真没做过,也听过有关内存池的,不过那是针对固定某个程序的。。。今天突然有点想法,写了段代码,不知对不对。。。
请大家从效率,语法,功能等方面给点批评和建议

注:VC6,直接贴到程序里就能用*/

// 内存管理类.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include "assert.h"
#include <vector>
#include <string>

using std::string;

class CManageMemory //内存管理类,实际应用中,数据可以向某文件中写入,以便查看错误
{
protected:

typedef struct //内存信息结构
{
void *MemAdd;
int RetAdd;
char FileName[256];
int CodeLine;
}MemInfo,*lpMemInfo;

std::vector<lpMemInfo> m_MemoryList; //内存块信息表

public:

~CManageMemory()
{
assert(m_MemoryList.size()==0);
ReleaseAll();
}

#define PLACE __FILE__,__LINE__
//函数功能:记录一个已分配的内存块
//参数1:内存块的起始位置
template<typename T>
T *New(T *p ,char *file,int line)
{
#ifdef _DEBUG
if(p!=NULL)
{
int *MyEbp; //得到分配该内存块的代码的下一句位置(eip位置),以用于查找错误
__asm
{
mov MyEbp,ebp
}

lpMemInfo pNewMem = new MemInfo;
pNewMem->MemAdd = p;
pNewMem->RetAdd = *(MyEbp+1); //保存该内存块的代码的下一句位置
strcpy(pNewMem->FileName,file);
pNewMem->CodeLine=line;
m_MemoryList.push_back(pNewMem);
}
#endif
return p;
}

//函数功能:释放已分配的内存块
//参数1:内存块的起始位置
void Delete(void *p)
{
#ifdef _DEBUG
std::vector<lpMemInfo>::iterator pIter = NULL;
for(pIter=m_MemoryList.begin();pIter<m_MemoryList.end();pIter++)
{
lpMemInfo pMem = *pIter;
if(pMem->MemAdd==p)
{
m_MemoryList.erase(pIter);
pIter--;
}
}
#endif
delete p;
}

//函数功能:该函数得到某内存块的大小
//参数1:内存块的起始地址
//返回值:内存块的字节大小
template<typename T>
int GetMemSize(T *p)
{
#ifdef _DEBUG
return *((int*)((char*)p-0x10)); //通过内存块信息得到内存块大小,该信息位于首地址-16的位置
#else
return 0;
#endif
}

//函数功能:该函数释放所有未释放的内存块
void ReleaseAll()
{
#ifdef _DEBUG
std::vector<lpMemInfo>::iterator pIter = NULL;
for(pIter=m_MemoryList.begin();pIter<m_MemoryList.end();pIter++)
{
lpMemInfo pMem=*pIter;
m_MemoryList.erase(pIter);
pIter--;
delete pMem;
}
#endif
}
//函数功能:此函数返回未释放的内存块数量
int GetLeakCount()
{
#ifdef _DEBUG
return m_MemoryList.size();
#else
return 0;
#endif
}
//函数功能:此函数返回未释放内存块的信息,以便程序员调试程序
//参数1: 第N处泄露的序号,在已知泄露次数的情况下
//参数2: 地址传递,返回泄露的下一句代码位置(EIP指向的位置)
//参数3: 地址传递,分配该内存块的文件名
//参数4: 地址传递,分配该内存块的文件所在行数
//返回值:返回泄露的内存地址
void *GetLeakInfo(int index,int *RetAdd=NULL,char *file=NULL,int *line=NULL)
{
#ifdef _DEBUG
assert(index<=m_MemoryList.size());
if(RetAdd!=NULL)
{
*RetAdd=m_MemoryList[index]->RetAdd;
}
if(file!=NULL)
{
strcpy(file,m_MemoryList[index]->FileName);
}
if(line!=NULL)
{
*line=m_MemoryList[index]->CodeLine;
}
return m_MemoryList[index]->MemAdd;
#else
return 0;
#endif
}

};
class Test //测试用类
{
int a[25];

public:
int b;
Test(int size):b(size){}
};

CManageMemory g_Memory; //全局内存管理对象


void main()
{
//用来测试的类对象
Test *a=g_Memory.New(new Test(5),PLACE);
string *b=g_Memory.New(new string, PLACE);
int *c=g_Memory.New(new int[100],PLACE);

printf("共有%d处内存未释放\n\n",g_Memory.GetLeakCount());

for(int i=g_Memory.GetLeakCount()-1;i>=0;i--)//查看各处内存块的信息
{
void *address=NULL; //地址
char file[256]={0}; //所在文件
int line=0; //所在行
int code=0; //代码位置
address=g_Memory.GetLeakInfo(i,&code,file,&line);

printf("第%d处泄露的内存块首地址为%x\n",i,address); //实际应用中最好向文件中写入
printf("该内存块长度为:%d字节\n",g_Memory.GetMemSize(address));
printf("该处泄露于EIP指向%x前一句分配\n",code);
printf("该处泄露位于文件%s第%d行\n",file,line);
printf("\n");
g_Memory.Delete(address);
}
printf("共有%d处内存未释放\n\n",g_Memory.GetLeakCount());
//g_Memory.ReleaseAll();
}

...全文
377 19 打赏 收藏 转发到动态 举报
写回复
用AI写文章
19 条回复
切换为时间正序
请发表友善的回复…
发表回复
ywchen2000 2006-02-09
  • 打赏
  • 举报
回复
内存管理,是不是模拟操作系统的最先适配 最佳适配.........
pagechen 2006-02-08
  • 打赏
  • 举报
回复
上次没仔细看,原来是内存泄露检测啊,只有测试时候用到啊,那就不用谈什么效率了。
vc_hunter 2006-02-08
  • 打赏
  • 举报
回复
恩,这个不算内存管理,只是做工程时辅助检测内存泄露的一个类。。。真正的内存管理应该是内存池那种,先分配足够的空间,然后在里面分配内存给外面。不过我不太懂,正常的内存管理类,如果效率比API高的话,那一定是专门针对某个程序的,是不是这样呢
caucyniu 2006-02-08
  • 打赏
  • 举报
回复
内存管理
用 vector就时别人在管理

你可以看一下STL源码 里面的allocator就是

它的大体思路:
维护一个FreeList 管理一个 8~128Byte 的内存
大于128就调用malloc
那才是真正的内存管理 你写的只是好像一个迭代器
效率不高
vc_hunter 2006-02-08
  • 打赏
  • 举报
回复
我就是想请教一下,通用的内存管理类存在吗?如果是通用的,我想API的功能不差,专用的话,就没什么好想的了,看情况搞内存池
huheng_0_0 2006-02-07
  • 打赏
  • 举报
回复
留名,学习ing
asdfg014 2006-02-07
  • 打赏
  • 举报
回复
有几处不明白:
1.在void ReleaseAll()函数中
为什么只delete pMem;而不加上delete pMem->MemAdd;句呢?
2.在int GetMemSize(T *p)中
为什么内存块的大小是*((int*)(char*)p-0x10))呢?

请高人指点
pagechen 2006-02-07
  • 打赏
  • 举报
回复
不用模板,重载new delete N 次。空间可以预先申请
对于内存管理,简单就是效率
laolaoliu2002 2006-02-07
  • 打赏
  • 举报
回复
没仔细看,不过特别有用,呵呵先保存下来
逸学堂 2006-02-07
  • 打赏
  • 举报
回复

1:才用模板?????啥意思
2:放弃stl
不好意思,是使用模板.
如果说vector简单,我完全赞同.
但是说vector效率高.那就不干苟同了.
vector策略是,增加对象时,一旦超过vector容量,vector会以当前2倍
容量的空间申请内存.然后把已经存在的数据拷贝到新的内存中去.
这个过程怎么说效率也不会高到那去.并且一旦发生这种情况,原先的指向指针都会出问题.

vc_hunter 2006-02-07
  • 打赏
  • 举报
回复
TO: ugg(逸学堂(exuetang.net))
多谢指点,我以前是听说vector效率高,所以就懒得自己动手了。
不过你说的出错应该不会的,我是通过vector的接口去访问内部数据,当他的内存块移动时,都在内部处理了。跟用户没关系
vc_hunter 2006-02-07
  • 打赏
  • 举报
回复
TO: asdfg014(绝望生鱼片)
有几处不明白:
1.在void ReleaseAll()函数中,为什么只delete pMem;而不加上delete pMem->MemAdd;句呢?
答:此处忘写了,嘿嘿
2.在int GetMemSize(T *p)中,为什么内存块的大小是*((int*)(char*)p-0x10))呢?
答:任何用new或malloc开辟的内存块起始地址-0x10处,都是一个32位的整数,表示此内存块的长度,所以当你free或delete时,系统才知道应该释放多少内存。我自己无意间发现的,以前一直不懂为什么操作系统知道能释放多少内存
vc_hunter 2006-02-07
  • 打赏
  • 举报
回复
TO: pagechen(天外飞来的仙)
当时的题是要求用类来实现,而且重载操作符和做个管理类来说,各有各的好处。。。而且,简单不等于效率
healer_kx 2006-02-07
  • 打赏
  • 举报
回复
挺好的,还需要测试。
vc_hunter 2006-02-06
  • 打赏
  • 举报
回复
楼上说的,没看懂。。。

1:才用模板?????啥意思
2:放弃stl

起始自己写个链表没什么难度,主要vector效率高,还简单。。。不知道为什么最好不用,解释解释好吗
逸学堂 2006-02-06
  • 打赏
  • 举报
回复
看了一部分,
发现一个问题,记录楼主说是自己的内存管理类.
但是是通过vector来管理的.所以,单一可能实现一个功能.
但是,不能通用.所以建议
1:才用模板
2:放弃STL.
vc_hunter 2006-02-06
  • 打赏
  • 举报
回复
有个地方忘加注释了,帖子编辑不了,这里补上

typedef struct//内存信息结构
{
void *MemAdd; //内存块起始地址
int RetAdd; //内存分配的代码地址的下一句EIP
char FileName[256]; //分配该内存的文件位置
int CodeLine; //代码行数位置
}MemInfo,*lpMemInfo;

比如
405b10c int *a=new int[100];
405b120 ......

那么MemAdd就是a的地址
RetAdd就是405b120
FileName里就是e:\内存管理类\内存管理.cpp这种
CodeLine里是是int型的行数
bm1408 2006-02-06
  • 打赏
  • 举报
回复
拷下来,回去给你看看~
bm1408 2006-02-06
  • 打赏
  • 举报
回复
可以看一下linux的部分源码~

你的程序没有看,
看是即然出了这个题目一般在寻址方面还需要你自己来控制的~

65,213

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧