【lesson2】定长内存池的实现

文章目录

  • 介绍
  • 定长内存池的设计
  • 定长内存池的实现
    • 需要成员变量
    • 需要的成员函数
    • 定长内存池结构
    • 定长内存池Delete(释放空间)的实现
    • 定长内存池New(申请空间)的实现
  • 定长内存池的实现完整版

介绍

作为程序员(C/C++)我们知道申请内存使用的是malloc,malloc其实就是一个通用的大众货,什么场景下都可以用,但是什么场景下都可以用就意味着什么场景下都不会有很高的性能,下面我们就先来设计一个定长内存池做个开胃菜,当然这个定长内存池在我们后面的高并发内存池中也是有价值的,所以学习他目的有两层,先熟悉一下简单内存池是如何控制的,第二他会作为我们后面内存池的一个基础组件。
在这里插入图片描述

定长内存池的设计

在这里插入图片描述
首先定长内存池的设计我们会向内存申请一大块空间,那么这么一大块空间我们肯定的知道在哪里,所以就用_memory指针指向该块空间
在这里插入图片描述
我们需要定义对象时,我们就只需要向内存池中的_memory申请一个对象大小的字节数就行了

我们被申请出去了一个或者多个对象大小的空间,那么一定会被还回来,所以我们就要对这些还回来的对象空间进行管理。
所以我们需要将这些还回来的对象,用单向链表管理起来
在这里插入图片描述
那么我们是如何用_freeList把一个一个对象链接起来的呢
我们可以用一个对象的前几个字节来存储下一个对象的地址。

定长内存池的实现

需要成员变量

在实现定长内存池之前我们要想,定长内存池需要哪些成员变量?

首先:我们向系统堆申请一定大小的空间,那么我们肯定要知道这块空间在哪里,所以第一个成员变量就是_memory指针,指向我们向系统申请的堆空间。
1._memory指针

其次:我们申请了对象就一定会被还回来,所以就要管理还回来的对象,所以第二个成员变量就是_freeList指针。
2._freeList指针

最后:我们_memory指向申请的堆空间如果一直被申请的话,那么申请的堆空间就一定会被使用殆尽,这时就需要向系统申请新的堆空间,那么我们该如何知道申请的堆空间是否被使用使用殆尽。所以就需要第三个成员变量_remainBytes记录剩余空间
3._remainBytes

需要的成员函数

除了成员变量我们还需要想定长内存池需要哪些成员函数?

首先:我们肯定需要一个成员函数,来为我们提供申请一个对象大小空间的窗口。
跟C++申请空间一样命名为New()。

最后:我们申请了一个对象大小的空间,那么最后肯定是要释放的,所以我们肯定要需要一个函数,来为我们提供释放空间的窗口
跟C++释放空间一样命名为Delete()。

定长内存池结构

在这里插入图片描述

定长内存池Delete(释放空间)的实现

Delete函数的逻辑很简单,我们只要把释放回来的对象空间,链接到_freeList即可,所以我们先实现Delete函数。

但是Delete我们也遇到了一个难题,还回来的是一个对象大小的空间啊,并不是一个对象啊。
那么我们如何把一个对象大小的空间链接到_freeList中呢?
这时我们就可以想到,我们可以一个对象大小空间的前4个字节存储指针的大小。
在这里插入图片描述
但是这时又遇到了一个问题,这个代码在32位平台下是可以的,但是在64位平台下指针是8个字节的该代码就不行了。
这时项目的高手就想到了一个办法。
在这里插入图片描述
在这里插入图片描述
(void**)在32位下解引用*(void**)是一个指针的指针,大小是4个字节。
(void**)在64位下解引用*(void**)也是一个指针的指针,大小是8个字节。

这时我们的问题就迎刃而解。

Delete函数的实现:

void Delete(T* obj)
	{
		// 头插
		*(void**)obj = _freeList;
		_freeList = obj;
	}

定长内存池New(申请空间)的实现

New申请空间的步骤:
1.先查看_freeList是否有空闲的一个对象大小的空间,我们优先把还回来内存块对象,再次重复利用。

if (_freeList)
{
	void* next = *((void**)_freeList);
	obj = (T*)_freeList;
	_freeList = next;
}

2.如果_freeList没有空闲的对象空间,那么就向_memory要一块,对象大小的空间。
但是要的时候我们还得注意_memory指向的系统堆空间是否已经使用殆尽了?
如果已经使用殆尽了,我们得先向系统申请一块大的堆空间。
那么如何判断空间是否已经使用殆尽呢?

// 剩余内存不够一个对象大小时,则重新开大块空间
if (_remainBytes < sizeof(T))
{
	_remainBytes = 128 * 1024;//自己规定的向系统堆空间申请的空间大小
	//_memory = (char*)malloc(_remainBytes);
	_memory = (char*)SystemAlloc(_remainBytes >> 13);//Windows下脱离malloc申请大块空间
	if (_memory == nullptr)
	{
		throw std::bad_alloc();
	}
}

这下我们就不考虑_memory指向的系统堆空间是否已经使用殆尽的问题了。
那么我们接下里就要向_memory要一个对象大小的空间。
那么如何要呢?
首先让obj指针_memory的首地址。
在这里插入图片描述
然后_memory += objSize,也就是_memory += 一个对象的大小。
在这里插入图片描述
这里大小可能也就明白了,为什么要把_memory定义成char的,因为char容易控制

然后我们把obj初始化,然后返给外层就可以了。

obj = (T*)_memory;//先把_memory的地址给obj
//然后计算要多少大小的空间,申请的空间大小 > 一个指针的大小 则用一个对象大小
//如果申请的空间大小 < 一个指针的大小 就用一个指针的大小
//因为我们要用对象的前几个字节存储地址,所以一个对象的大小必须 >= 一个指针
size_t objSize = sizeof(T) < sizeof(void*) ? sizeof(void*) : sizeof(T);
_memory += objSize;
_remainBytes -= objSize;

New函数的实现:

T* New()
	{
		T* obj = nullptr;

		// 优先把还回来内存块对象,再次重复利用
		if (_freeList)
		{
			void* next = *((void**)_freeList);
			obj = (T*)_freeList;
			_freeList = next;
		}
		else
		{
			// 剩余内存不够一个对象大小时,则重新开大块空间
			if (_remainBytes < sizeof(T))
			{
				_remainBytes = 128 * 1024;
				//_memory = (char*)malloc(_remainBytes);
				_memory = (char*)SystemAlloc(_remainBytes >> 13);
				if (_memory == nullptr)
				{
					throw std::bad_alloc();
				}
			}

			obj = (T*)_memory;
			size_t objSize = sizeof(T) < sizeof(void*) ? sizeof(void*) : sizeof(T);
			_memory += objSize;
			_remainBytes -= objSize;
		}

		// 定位new,显示调用T的构造函数初始化
		new(obj)T;

		return obj;
	}

定长内存池的实现完整版

#pragma once
#include <iostream>
#include <vector>
#include <time.h>
using std::cout;
using std::endl;

#ifdef _WIN32
#include<windows.h>
#else
// 
#endif

// 直接去堆上按页申请空间
inline static void* SystemAlloc(size_t kpage)
{
#ifdef _WIN32
	void* ptr = VirtualAlloc(0, kpage << 13, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
#else
	// linux下brk mmap等
#endif

	if (ptr == nullptr)
		throw std::bad_alloc();

	return ptr;
}

template<class T>
class ObjectPool
{
public:
	T* New()
	{
		T* obj = nullptr;

		// 优先把还回来内存块对象,再次重复利用
		if (_freeList)
		{
			void* next = *((void**)_freeList);
			obj = (T*)_freeList;
			_freeList = next;
		}
		else
		{
			// 剩余内存不够一个对象大小时,则重新开大块空间
			if (_remainBytes < sizeof(T))
			{
				_remainBytes = 128 * 1024;
				//_memory = (char*)malloc(_remainBytes);
				_memory = (char*)SystemAlloc(_remainBytes >> 13);
				if (_memory == nullptr)
				{
					throw std::bad_alloc();
				}
			}

			obj = (T*)_memory;
			size_t objSize = sizeof(T) < sizeof(void*) ? sizeof(void*) : sizeof(T);
			_memory += objSize;
			_remainBytes -= objSize;
		}

		// 定位new,显示调用T的构造函数初始化
		new(obj)T;

		return obj;
	}

	void Delete(T* obj)
	{
		// 显示调用析构函数清理对象
		obj->~T();

		// 头插
		*(void**)obj = _freeList;
		_freeList = obj;
	}

private:
	char* _memory = nullptr; // 指向大块内存的指针
	size_t _remainBytes = 0; // 大块内存在切分过程中剩余字节数

	void* _freeList = nullptr; // 还回来过程中链接的自由链表的头指针
};

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/367355.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

谷歌产品大更新:Bard可生成图像;文生音乐平台等5大免费功能

2月2日&#xff0c;谷歌在官网对生成式AI产品进行了大更新&#xff0c;包括类ChatGPT聊天助手Bard可以通过文本提示生成图像&#xff1b; 全新的文生音乐平台MusicFX&#xff1b;新的文生图像平台ImageFX&#xff1b;新的文本扩写平台TextFX&#xff1b;在谷歌地图中增加生成式…

Open3D 深度图像转点云

目录 一、算法原理1、算法过程2、主要函数3、算法源码二、代码实现三、结果展示1、深度图像2、点云四、测试数据

Python详细教程

一、Python简历 Python 是一个高层次的结合了解释性、编译性、互动性和面向对象的脚本语言。 Python 的设计具有很强的可读性&#xff0c;相比其他语言经常使用英文关键字&#xff0c;其他语言的一些标点符号&#xff0c;它具有比其他语言更有特色语法结构。 Python 是一种解…

客户端和服务端的简介

Client 和 Server 客户端&#xff08;Client&#xff09; 或称用户端&#xff0c;是指与服务器相对应&#xff0c;为客户提供本地服务的程序。除了一些只在本地运行的应用程序之外&#xff0c;一般安装在客户机上&#xff0c;需要与服务端互相配合运行。例如&#xff1a;下载 Q…

jvm基础篇之垃圾回收[3](垃圾回收器)

文章目录 分代GC代取划分原因垃圾回收器组合关系年轻代-Serial垃圾回收器老年代-SerialOld垃圾回收器年轻代-ParNew垃圾回收器老年代-CMS垃圾回收器年轻代-Parallel Scavenge垃圾回收器老年代-Parallel Old垃圾回收器 G1垃圾回收器G1内存结构G1回收方式年轻代回收混合回收FULL …

安全通信设置:使用 OpenSSL 为 Logstash 和 Filebeat 提供 SSL 证书

在为 Elasticsearch 采集数据时&#xff0c;我们经常使用到 Filebeat 及 Logstash。在我们之前的很多教程中&#xff0c;我们通常不为 Filebeat 和 Logstash 之前的通信做安全配置。 如何为 Filebeat 及 Logstash 直接建立安全的链接&#xff1f;这个在很多的情况下是非常有用的…

2024美赛A题七鳃鳗种群复杂系统动力学模型完整成品论文和代码

经过不懈的努力&#xff0c;2024美赛A题完整成品论文和代码已完成&#xff0c;代码为A题全部4问的代码&#xff0c;论文包括摘要、问题重述、问题分析、模型假设、符号说明、模型的建立和求解&#xff08;问题1七鳃鳗种群竞争模型的建立和求解、问题2种群优势劣势评估模型的建立…

很多人不看好造车新势力,我却坚信他们一定会成功

最近我国出现了很多新能源汽车品牌&#xff0c;除了理小蔚之外&#xff0c;最近爆火的华为与赛力斯合作的问界以及小米借用北汽生产的小米SU7汽车。可能是于大嘴和雷布斯营销过度了&#xff0c;引起了很多网民的质疑&#xff0c;更是引来了汽车大佬长安董事长的担忧。朱董事长说…

如何取消隐藏Excel中的行?这里提供详细步骤

取消隐藏Microsoft Excel电子表格中的所有行就像按下键盘快捷键或使用功能区上的按钮一样简单。我们将向你展示如何操作。 如何使用快捷方式取消隐藏Excel中的所有行 若要在电子表格中显示隐藏行&#xff0c;请使用Microsoft Excel启动电子表格。然后&#xff0c;访问包含隐藏…

超详细Anconda pytorch cuda cuDNN安装及介绍(李沐老师视频环境)

零、准备知识阶段 ⇲ 显卡驱动、CUDA、cuDNN之间联系以及安装配置 在配置PyTorch的过程中&#xff0c;显卡驱动、CUDA、cuDNN三者之间的关系、作用以及在众多版本中如何搭配一直困扰着我。虽然网上资料很多&#xff0c;但各说其词&#xff0c;即使最终迈过种种坑成功运行&…

快充协议的奥秘:工作原理与特性比较

文章目录 一、 前言二、快充协议1.公有协议1.1 PD协议介绍发展史USB-IF组织PPS快充协议 1.2 QC协议介绍发展史 1.3 PE协议介绍 2.私有协议2.1 VOOC 闪充2.2 FCP/SCP 闪充2.3 FlashCharge闪充2.4 MIChargeTurbo闪充2.5 AFC闪充2.6 mCharge快充 三、总结 一、 前言 最近&#xf…

【深度学习】数据归一化/标准化 Normalization/Standardization

目录 一、实际问题 二、归一化 Normalization 三、归一化的类型 1. Min-max normalization (Rescaling) 2. Mean normalization 3.Z-score normalization (Standardization) 4.非线性归一化 4-1 对数归一化 4-2 反正切函数归一化 4-3 小数定标标准化&#xff08;Demi…

echarts中绘制3D三维地球

简介 echarts中的三维地球&#xff0c;需要用到世界地图json数据&#xff0c;我把json文件放到我的资源中&#xff0c;有需要的自行下载。 安装插件 // 安装echats npm install echarts --save npm install echarts-gl --save 项目中引用 1&#xff0c;引入安装的echarts…

Http请求Cookie失效问题

Http请求Cookie失效问题记录 一、问题现象 在开发功能的过程中&#xff0c;业务依赖cookie进行取之&#xff0c;项目进行交互时会对前端http请求携带的cookies进行解析操作&#xff0c;但在自测调试对过程中出现账户的授权失效的报错问题。 二、问题排查 用arthas进行代码方…

【国产MCU】-CH32V307-GPIO控制:输入与输出

GPIO控制:输入与输出 文章目录 GPIO控制:输入与输出1、GPIO简单介绍2、驱动API介绍3、GPIO配置代码实现3.1 GPIO配置为输出3.2 GPIO配置为输入CH32V307的GPIO口可以配置成多种输入或输出模式,内置可关闭的上拉或下拉电阻,可以配置成推挽或开漏功能。GPIO口还可以复用成其他…

【24美赛思路已出】2024年美赛A~F题解题思路已出 | 无偿自提

A题&#xff1a;资源可用性和性别比例 问题一&#xff1a; 涉及当灯鱼种群的性别比例发生变化时&#xff0c;对更大的生态系统产生的影响。为了分析这个问题&#xff0c;可以采用以下的数学建模思路&#xff1a;建立灯鱼种群模型&#xff1a; 首先&#xff0c;建立一个灯鱼种群…

冰冻天气恰逢春运,“观冰精灵”化身电力供应守护者

据中国路网&#xff0c;截至2月1日14时&#xff0c;受降雪及路面结冰影响&#xff0c;河北、山西、内蒙古、黑龙江、江苏、安徽、河南、山东、西藏、陕西、宁夏、甘肃、新疆共封闭路段66个&#xff08;涉及44条高速公路、5条普通国道、5条普通省道&#xff09;&#xff0c;关闭…

基于大数据的淘宝电子产品数据分析的设计与实现

&#xff08;1&#xff09;本次针对开发设计系统并设置了相关的实施方案&#xff0c;利用完整的软件开发流程进行分析&#xff0c;完成了设置不同用户的操作权限和相关功能模块的开发&#xff0c;最后对系统进行测试。 &#xff08;2&#xff09;框架可以帮助程序开发者快速构建…

2024 Flutter 重大更新,Dart 宏(Macros)编程开始支持,JSON 序列化有救

说起宏编程可能大家并不陌生&#xff0c;但是这对于 Flutter 和 Dart 开发者来说它一直是一个「遗憾」&#xff0c;这个「遗憾」体现在编辑过程的代码修改支持上&#xff0c;其中最典型的莫过于 Dart 的 JSON 序列化。 举个例子&#xff0c;目前 Dart 语言的 JSON 序列化高度依…

PHP集成开发 -- PhpStorm 2023

PhpStorm 2023是一款强大的PHP集成开发环境&#xff08;IDE&#xff09;&#xff0c;旨在提高开发人员的生产力和代码质量。以下是关于PhpStorm 2023软件的详细介绍&#xff1a; 首先&#xff0c;PhpStorm 2023提供了丰富的代码编辑功能&#xff0c;包括语法高亮、自动补全、代…