一个最简单的内存池AutoMemory

1.Linux/C/Python 专栏收录该内容
48 篇文章 0 订阅

    C/C++中内存管理是个最麻烦的事情,内存申请释放,内存泄露,内存越界,甚至是内存碎片,就会导致程序出Core或者变慢。如何有效的管理内存,有很多方法,我认为最简单的方式是用一个内存池来管理内存。

    谈到内存池的时候,就有必要说下程序的生命周期和作用域,数据分为三类:1类是进程数据(全局数据)。2、线程数据,每一个线程一份。3、请求数据,每一次调用一份。

        

    如果一个内存池想什么生命周期和作用域的数据都放在里面,可能是不合适的。所以我建议的使用方式是:进程一个内存池、每一个线程一个内存池、每个请求一个内存池。

    在进程/线程/请求初始时初始内存池,在进程/线程/请求结束时销毁内存池。

    所以,就有了下面这个非常简单的内存池了,代码有一点点绕,不过仔细阅读还是能理解的。

    头文件 AutoMemory.h

#ifndef _AUTO_MEMORY_H__
#define _AUTO_MEMORY_H__

#include <stddef.h>

//#define _MEM_TEST_
//#define _MEM_DEBUG_
#define _MEM_USE_

//default 1M
#define MEMORY_BLOCK_SIZE 1000000


/*
 * 线程兼容,自动释放
 */
class AutoMemory
{
public:
	AutoMemory();
	AutoMemory(int block_size);
	~AutoMemory();
	void* Alloc(size_t size);
	void Free(void* ptr);
	void FreeAll();

	void Debug();
	int BlockCount();
	size_t LeftSize();
	size_t MemSize();

private:
	struct MemBlock{
		MemBlock* prev;
	};
private:
	int headerSize;
	int blockSize;
	size_t memSize;
	int blockCount;
	char* begin;
	char* end;
	//MemBlock* currBlock;
};

#endif

   CPP文件AutoMemory.cpp

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "AutoMemory.h"

AutoMemory::AutoMemory(){
	blockSize =  MEMORY_BLOCK_SIZE;
	blockCount = 0;
	memSize = 0;
	headerSize = sizeof(MemBlock);
	begin = end = ( char* ) headerSize;
}

AutoMemory::AutoMemory(int block_size){
	blockSize =  block_size;
	blockCount = 0;
	memSize = 0;
	headerSize = sizeof(MemBlock);
	begin = end = ( char* ) headerSize;
}

AutoMemory::~AutoMemory(){
	FreeAll();
}

size_t AutoMemory::MemSize(){
	return memSize;
}

int AutoMemory::BlockCount(){
	return blockCount;
}

size_t AutoMemory::LeftSize(){
	return (size_t)(end-begin);
}

void AutoMemory::Debug(){
	printf("Block count %d, Left size %d, Total size %d\n",
			this->BlockCount(),
			this->LeftSize(),
			this->MemSize() );
}

void* AutoMemory::Alloc(size_t size){
#ifndef _MEM_USE_
	return malloc(size);
#endif

	if ( (size_t)( end - begin ) < size ){
		if ( size >= blockSize){
			char* ptr = (char*)malloc(headerSize + size);
			MemBlock* pNew = (MemBlock*)ptr;
			MemBlock* pHeader = (MemBlock*)(begin - headerSize);
			if ( pHeader ){
				pNew->prev = pHeader->prev;
				pHeader->prev = pNew;
			}else{
				end = begin = (char*)( ptr + headerSize );
				pNew->prev = NULL;
			}
			blockCount += 1;
			memSize += size;
			return end;
		} else{
			char* ptr = (char*)malloc(headerSize + blockSize);
			MemBlock* pNew = (MemBlock*)ptr;
			pNew->prev = (MemBlock*)(begin - headerSize);
			begin = (char*)(ptr + headerSize);
			end = begin + blockSize;
			blockCount += 1;
			memSize += blockSize;

		}
	}
	return end -= size;
}

void AutoMemory::Free(void* ptr){
#ifndef _MEM_USE_
	free( ptr );
#endif
}

void AutoMemory::FreeAll(){
	MemBlock* pHeader = (MemBlock*)(begin - headerSize);
	while( pHeader ){
		MemBlock* pTemp = pHeader->prev;
        free( pHeader );
		pHeader = pTemp;
	}
	begin = end = (char*)headerSize;
	memSize = 0;
	blockCount = 0;
}

#ifdef _MEM_TEST_
int main(){
	AutoMemory am(100);
	printf("idx 1, alloc 10\n");
	char* buf = (char*)am.Alloc(10);
	am.Debug();

	printf("idx 2, alloc 90\n");
	am.Alloc(90);
	am.Debug();

	printf("idx 3, alloc 10\n");
	am.Alloc(10);
	am.Debug();

	printf("idx 4, alloc 100\n");
	am.Alloc(100);
	am.Debug();

	printf("idx 5, alloc 10\n");
	am.Alloc(10);
	am.Debug();
}
#endif





  • 1
    点赞
  • 0
    评论
  • 0
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

相关推荐
<p style="color:#666666;"> <span style="font-size:14px;">本门课程重实战,将基础知识拆解到项目里,让你在项目情境里学知识。</span> </p> <p style="color:#666666;"> <span style="font-size:14px;">这样学习方式能让你保持兴趣、充满动力,时刻知道学东西能用在哪、能怎么用。</span> </p> <p style="color:#666666;"> <span style="font-size:14px;">平时不明白知识点,放在项目里去理解就恍然大悟了。</span> </p> <p style="color:#666666;"> <span></span> </p> <p style="color:#666666;"> <span style="font-size:14px;"> </span> </p> <p style="color:#666666;"> <span style="color:#FF0000;font-size:14px;"><strong>一、融汇贯通</strong></span> </p> <p style="color:#666666;"> <span style="font-size:14px;">本视频采用了前后端分离开发模式,前端使用Vue.js+Element UI实现了Web页面呈现,后端使用Python Django框架实现了数据访问接口,前端通过Axios访问后端接口获得数据。在学习完本章节后,真正理解前后端各自承担工作。</span> </p> <p style="color:#666666;"> <span style="font-size:14px;"> </span> </p> <p style="color:#666666;"> <span style="color:#FF0000;font-size:14px;"><strong>二、贴近实战</strong></span> </p> <p style="color:#666666;"> <span style="font-size:14px;">本系列课程为练手项目实战:学生管理系统v4.0开发,项目包含了如下几个内容:项目总体介绍、基本功能演示、Vuejs初始化、Element UI使用、在Django中实现针对数据增删改查接口、在Vuejs中实现前端增删改查调用、实现文件上传、实现表格分页、实现导出数据到Excel、实现通过Excel导入数据、实现针对表格批量化操作等等,所有功能都通过演示完成、贴近了实战</span> </p> <p style="color:#666666;"> <span style="font-size:14px;"> </span> </p> <p style="color:#666666;"> <span style="color:#FF0000;font-size:14px;"><strong>三、课程亮点</strong></span> </p> <p style="color:#666666;"> <span style="font-size:14px;">在本案例中,亮点在于前后端做了分离,真正理解前后端各自承担工作。前端如何和后端交互</span> </p> <p style="color:#666666;"> <span style="font-size:14px;"> </span> </p> <p style="color:#666666;"> <span style="color:#FF0000;font-size:14px;"><strong>适合人群:</strong></span> </p> <p style="color:#666666;"> <span style="font-size:14px;">1、有Python语言基础、web前端基础,想要深入学习Python Web框架朋友;</span> </p> <p style="color:#666666;"> <span style="font-size:14px;">2、有Django基础,但是想学习企业级项目实战朋友;</span> </p> <p style="color:#666666;"> <span style="font-size:14px;">3、有MySQL数据库基础朋友</span> </p> <p style="color:#666666;"> <span style="font-size:14px;"> </span> </p> <p style="color:#666666;"> <span style="font-size:14px;"><img alt="" src="https://img-bss.csdnimg.cn/202009070752197496.png" /><br /> </span> </p> <p style="color:#666666;"> <span style="font-size:14px;"><br /> </span> </p>
©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值