STL空间配置器

本文介绍了STL空间配置器的工作原理,包括第一级和第二级配置器的作用机制。第一级配置器处理大块内存分配,而第二级配置器则通过自由链表和内存池来提高小对象内存分配的效率,解决了内存碎片问题,并提升了内存分配速度。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

STL空间配置器分为第一级配置器与第二级配置器,主要用来对内存的申请与释放。

第一级配置器:调用的是malloc/free,并有 new-handle 机制

第二级配置器:由自由链表及内存池组成

                           自由链表一个存储16个空闲块列表表头的数组free_list;

                      内存池起始地址的指针start_free和一个指向结束地址的指针end_free之间的内存

程序中的小对象的分配极易造成内存碎片(也叫外碎片),给操作系统的内存管理带来了很大压力,系统中碎片的增多不但会影响内存分配的速度,而且会极大地降低内存的利用率。

使用空间配置器,提高了空间的利用率和内存的分配速度,主要原因是:

(1)当内存申请超过128字节时,就会被视为大块内存,由第一级空间配置器处理;

(2)当内存申请小于等于128字节时,会对其使用二级空间配置

       a) 先查找自由链表,如有空间,直接分配即可;

       b)当a)不满足时,便会向内存池申请大块内存,一块返回申请,另外的挂到自由链表上,当反复申请该大小内存时,便极大的 提高了分配速度;

       c)当内存池内存不足时,只返回满足要求的申请即可,适量分配空间;

       d) 当内存池也满足不了要求时,便会向系统 malloc 一大段空间给内存池,再继续满足申请

       e) 当系统内存紧张时,便会返回到看自由链表是否有闲置空间可释放至内存池;

       f)  到山穷水尽的地步,便移交第一级空间配置器处理

优点:(1)小对象的内存申请与释放快速(不用每次都要操作系统完成);

        (2)解决了内存碎片的问题(外碎片);

        (3)提高了空间利用率

缺点:引入了内碎片的问题

//第一级空间配置
template<int inst>
class __MallocAllocTemplate
{
public:
	static void *Oom_Malloc(size_t size)
	{
		void(*my_malloc_handler)();
		void *result;

		while (1)
		{
			my_malloc_handler = __Malloc_Alloc_Oom_Handler;
			if (my_malloc_handler == NULL)
			{
				throw bad_alloc();
			}
			(*my_malloc_handler)();
			result = malloc(size);
			if (result) 
				return(result);
		}
	}
	static void * Allocate(size_t n)
	{
		void *result = malloc(n);
		if (0 == result)
			result = Oom_Malloc(n);
		return result;
	}

	static void Deallocate(void *p, size_t /* n */)
	{
		free(p);
	}
	static void(*Set_Malloc_Handler(void(*f)()))()
	{
		void(*old)() = __Malloc_Alloc_Oom_Handler;
		__Malloc_Alloc_Oom_Handler = f;
		return(old);
	}
private:
	static void(*__Malloc_Alloc_Oom_Handler)();
};
template<int inst>
void(*__MallocAllocTemplate<inst>::__Malloc_Alloc_Oom_Handler)() = NULL;


//第二级空间配置
template <bool threads, int inst>
class __Default_Alloc_Template
{
public:
	static void* Allocate(size_t n)
	{
		if (n > __MAX_BYTES)
			return __MallocAllocTemplate<0>::Allocate(n);
		size_t index = FREELIST_INDEX(n);
		void* result = NULL;
		if (free_list[index] == NULL)//如果自由串上没有内存,就去内存池上找空间
			result = Refill(ROUND_UP(n));
		else
		{
			result = free_list[index];
			free_list[index] = free_list[index]->free_list_link;
		}
		return result;
	}
	static void* Refill(size_t n)
	{
		size_t nobjs = 20;
		char * chunk = chunk_alloc(n, nobjs);//通过chunk_alloc函数获得内存
		void* result = (void*)chunk;//把第一个满足的空间分配返回给申请者
		if (nobjs == 1)
			return result;

		//把剩下的多分出的内存空间挂到自由链表上
		else
		{
			size_t index = FREELIST_INDEX(n);
			obj* cur = NULL;
			obj* next = (obj*)((char*)chunk + n);
			free_list[index] = next;
			size_t i = 1;
			for (; i < nobjs; i++)
			{
				cur = next;
				next = (obj*)((char*)next + n);
				cur->free_list_link = next;
			}
			cur->free_list_link = NULL;
		}
		return result;
	}
	static char* chunk_alloc(size_t n, size_t& nobjs)
	{
		size_t totalbytes = n*nobjs;
		size_t poolbytes = _end_free - _start_free;//内存池现有的内存情况
		char* result;//返回分配的内存
		if (poolbytes >= totalbytes)
		{
			result = _start_free;
			_start_free += totalbytes;//降低水位线,内存池内存减少
			return  result;
		}
		else if (poolbytes > n)//内存池满足不了一次分配20个该大小的内存,但至少满足一个(够需求)
		{
			nobjs = poolbytes / n;//当前内存池可满足多少个n
			totalbytes = n*nobjs;
			result = _start_free;
			_start_free += totalbytes;
			return result;
		}
		else
		{//内存池的内存不足

			//重新为内存池申请大小,大小为bytes_to_get
			size_t bytes_to_get = 2 * totalbytes + ROUND_UP(_heap_size >> 4);
			//1、先把内存池中剩余的内存挂到自由链表的相应位置上
			if (poolbytes > 0)
			{
				size_t index = FREELIST_INDEX(poolbytes);
				((obj*)_start_free)->free_list_link = free_list[index];
				free_list[index] = (obj*)_start_free;
			}
			_start_free = (char*)malloc(bytes_to_get);
			if (_start_free == 0)
			{//申请内存失败
				//解决方法:在自由链表上比它大的位置查找是否有空闲内存
				for (size_t i = n; i <= __MAX_BYTES; i += __ALIGN)
				{
					size_t index = FREELIST_INDEX(n);
					obj* p = free_list[index];
					if (p != 0)
					{//找到满足要求的内存
						free_list[index] = free_list[index]->free_list_link;
						_start_free = (char*)p;
						_end_free = _start_free + n;
						return chunk_alloc(n, nobjs);
					}
				}
				//自由链表上没有可提供的内存,就只能转第一种空间配置的方法了
				_start_free = (char*)__MallocAllocTemplate<0>::Allocate(bytes_to_get);
			}
			_heap_size += bytes_to_get;
			_end_free = _start_free + bytes_to_get;
			return(chunk_alloc(n, nobjs));
		}
	}
	static void Deallocate(void*p, size_t n)
	{
		if (n > __MAX_BYTES)
		{
			__MallocAllocTemplate<0>::Deallocate(p, n);
		}
		else
		{
			obj* tmp = (obj*)p;
			size_t index = FREELIST_INDEX(n);
			tmp->free_list_link = free_list[index];
			free_list[index] = tmp;
		}
	}
protected:
	static size_t FREELIST_INDEX(size_t n)
	{
		return (n + __ALIGN - 1) / __ALIGN - 1;
	}
	static size_t ROUND_UP(size_t bytes)//保证字节数与8字节对齐
	{
		return (((bytes)+__ALIGN - 1) & ~(__ALIGN - 1));
	}
private:
	enum { __ALIGN = 8 };
	enum { __MAX_BYTES = 128 };
	enum { __NFREELISTS = __MAX_BYTES / __ALIGN };

	union obj 
	{
		union obj * free_list_link;//下一个节点
		char client_data[1];    /* The client sees this.        */
	};


	//自由链表
	static obj *  free_list[__NFREELISTS];

	//内存池
	static char * _start_free;
	static char * _end_free;
	static size_t _heap_size;//总共为内存池分配的空间字节数
};

template <bool threads, int inst>
typename __Default_Alloc_Template<threads, inst>::obj *   __Default_Alloc_Template<threads, inst>::free_list[__NFREELISTS] = { NULL };


template <bool threads, int inst>
char* __Default_Alloc_Template<threads, inst>::_start_free = NULL;

template <bool threads, int inst>
char* __Default_Alloc_Template<threads, inst>::_end_free = NULL;

template <bool threads, int inst>
size_t __Default_Alloc_Template<threads, inst>::_heap_size = 0;



标题基于SpringBoot+Vue的学生交流互助平台研究AI更换标题第1章引言介绍学生交流互助平台的研究背景、意义、现状、方法创新点。1.1研究背景意义分析学生交流互助平台在当前教育环境下的需求及其重要性。1.2国内外研究现状综述国内外在学生交流互助平台方面的研究进展实践应用。1.3研究方法创新点概述本研究采用的方法论、技术路线及预期的创新成果。第2章相关理论阐述SpringBootVue框架的理论基础及在学生交流互助平台中的应用。2.1SpringBoot框架概述介绍SpringBoot框架的核心思想、特点及优势。2.2Vue框架概述阐述Vue框架的基本原理、组件化开发思想及前端的交互机制。2.3SpringBootVue的整合应用探讨SpringBootVue在学生交流互助平台中的整合方式及优势。第3章平台需求分析深入分析学生交流互助平台的功能需求、非功能需求及用户体验要求。3.1功能需求分析详细阐述平台的各项功能需求,如用户管理、信息交流、互助学习等。3.2非功能需求分析对平台的性能、安全性、可扩展性等非功能需求进行分析。3.3用户体验要求从用户角度出发,提出平台在易用性、美观性等方面的要求。第4章平台设计实现具体描述学生交流互助平台的架构设计、功能实现及前后端交互细节。4.1平台架构设计给出平台的整体架构设计,包括前后端分离、微服务架构等思想的应用。4.2功能模块实现详细阐述各个功能模块的实现过程,如用户登录注册、信息发布查看、在线交流等。4.3前后端交互细节介绍前后端数据交互的方式、接口设计及数据传输过程中的安全问题。第5章平台测试优化对平台进行全面的测试,发现并解决潜在问题,同时进行优化以提高性能。5.1测试环境方案介绍测试环境的搭建及所采用的测试方案,包括单元测试、集成测试等。5.2测试结果分析对测试结果进行详细分析,找出问题的根源并
内容概要:本文详细介绍了一个基于灰狼优化算法(GWO)优化的卷积双向长短期记忆神经网络(CNN-BiLSTM)融合注意力机制的多变量多步时间序列预测项目。该项目旨在解决传统时序预测方法难以捕捉非线性、复杂时序依赖关系的问题,通过融合CNN的空间特征提取、BiLSTM的时序建模能力及注意力机制的动态权重调节能力,实现对多变量多步时间序列的精准预测。项目不仅涵盖了数据预处理、模型构建训练、性能评估,还包括了GUI界面的设计实现。此外,文章还讨论了模型的部署、应用领域及其未来改进方向。 适合人群:具备一定编程基础,特别是对深度学习、时间序列预测及优化算法有一定了解的研发人员和数据科学家。 使用场景及目标:①用于智能电网负荷预测、金融市场多资产价格预测、环境气象多参数预报、智能制造设备状态监测预测维护、交通流量预测智慧交通管理、医疗健康多指标预测等领域;②提升多变量多步时间序列预测精度,优化资源调度和风险管控;③实现自动化超参数优化,降低人工调参成本,提高模型训练效率;④增强模型对复杂时序数据特征的学习能力,促进智能决策支持应用。 阅读建议:此资源不仅提供了详细的代码实现和模型架构解析,还深入探讨了模型优化和实际应用中的挑战解决方案。因此,在学习过程中,建议结合理论实践,逐步理解各个模块的功能和实现细节,并尝试在自己的项目中应用这些技术和方法。同时,注意数据预处理的重要性,合理设置模型参数网络结构,控制多步预测误差传播,防范过拟合,规划计算资源训练时间,关注模型的可解释性和透明度,以及持续更新迭代模型,以适应数据分布的变化。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值