C/C++语言通过动态链表实现按需内存分配和使用(Linux Ubuntu 24.04环境)

我认为比较理想的内存使用方式应该实现这几个特性:

1. 分配一块能满足大多数情况下需求的内存,比如80%的情况下都不需要再次分配内存。

2. 对另外20%需要较多内存的情况,可以通过动态链表按需追加新的内存块。

3. 要对总共消耗的内存有一个最大数量限制,比如200M。

下面就是一个比较理想的通过动态链表实现按需内存分配和使用的例子,取名MemChain

#define BudaMc(size) (char*)alloc(size)
#define BudaM(T) (T*)alloc(sizeof(T))
#define BudaMn(T, name) T *name = (T*)alloc(sizeof(T))
#define BudaZ(T, name) T name; memset(&name, 0, sizeof(name))
#define BudaFree(m) if(m){ free(m); m = NULL; }
#define BudaMax(a, b) ((a)<(b)?(b):(a))typedef struct mem_chain_block
{char *mem;struct mem_chain_block *next;int size;int used;
} MemChainBlock;
typedef struct mem_chain
{struct mem_chain_block *first;struct mem_chain_block *last;int max_size;int used;            // sum of allocated mem of blocksint blocks_used;     // sum of used bytes of blocksint block_min_size;int block_count;
} MemChain;// calloc memory, log fail message
void* alloc(int size);
// MUST use free_mem_chain to free heap mem used
MemChain* create_mem_chain(int max_size=100002048, int block_min_size=2048);
// destroy the whole mem_chain
void free_mem_chain(MemChain *mc);
// delete all the blocks except the first one, reset mem_chain to the beginning
void reset_mem_chain(MemChain *mc);
// return NULL if failed
MemChainBlock* mem_chain_add_block(MemChain *mc, int size);
// If the memory size to use is known to be size, use this function; otherwise, use the next function. 
// Return NULL if failed, return the start of used memory if succeed.
char* use_mem_chain(MemChain *mc, int size, char* content=NULL);
// Return NULL if failed, return the start of used memory if succeed.
char* use_mem_chain(MemChain *mc, const char* format, ...);namespace BUDA
{void* alloc(int size){if (size <= 0) { log("alloc size cannot be less than 1\n"); return NULL; }void* r = calloc(1, size); if (!r) { log("alloc %d bytes memory failed.\n", size); return NULL; }  return r;}MemChain* create_mem_chain(int max_size, int block_min_size){log("create_mem_chain %d/%d", max_size, block_min_size);BudaMn(MemChain, mc); BudaMn(MemChainBlock, mcb); if(mc==NULL || mcb == NULL) return NULL;mcb->mem=BudaMc(block_min_size); if(mcb->mem == NULL) return NULL; mcb->size=block_min_size; mc->max_size=max_size; mc->used+=mcb->size; mc->block_min_size=block_min_size; mc->first=mc->last=mcb; mc->block_count=1;return mc;}  MemChainBlock* mem_chain_add_block(MemChain *mc, int size){log("mem_chain_add_block %d", size);if(size+mc->used > mc->max_size) { log("mem_chain reached max_size: %d", mc->max_size); return NULL; }BudaMn(MemChainBlock, mcb); if(mcb == NULL) return NULL;mcb->mem=BudaMc(size); if(mcb->mem == NULL) return NULL; mcb->size=size; mc->used+=size; mc->block_count++; mc->last->next=mcb; mc->last=mcb;return mcb;}void free_mem_chain(MemChain *mc){log("free_mem_chain %d", mc->used);int remain_block_count = mc->block_count; MemChainBlock *mcb=mc->first, *next; BudaFree(mc);while(mcb) { next=mcb->next; BudaFree(mcb->mem); BudaFree(mcb); remain_block_count--; mcb=next; }if(remain_block_count) { log("MemChain block_count broken: %d", remain_block_count); }}void reset_mem_chain(MemChain *mc){log("reset_mem_chain %d/%d", mc->max_size, mc->block_min_size);MemChainBlock *first=mc->first; MemChainBlock *mcb=first->next, *next; while(mcb) { next=mcb->next; BudaFree(mcb->mem); BudaFree(mcb); mcb=next; }mc->block_count=1; mc->blocks_used=0; mc->last=first; mc->used=first->size;first->next=NULL; first->used=0;}char* use_mem_chain(MemChain *mc, int size, char* content){log("use_mem_chain %d bytes", size);MemChainBlock *last=mc->last;if(last->used + size > last->size){int asize=BudaMax(mc->block_min_size, size); last = mem_chain_add_block(mc, asize); if(last==NULL) return NULL;}char* write_start=last->mem + last->used; last->used += size; mc->blocks_used+=size;if(content) memcpy(write_start, content, size);return write_start;}char* use_mem_chain(MemChain *mc, const char* format, ...){//log("try use_mem_chain : %s", format);MemChainBlock *last=mc->last; int used=last->used; char *write_start=last->mem+used; int remain=last->size - used, len, asize=mc->block_min_size;write: va_list args; va_start(args, format); len = vsnprintf2(last->mem + used, remain, format, args); va_end(args);if(len == -1) {last = mem_chain_add_block(mc, asize); if(last==NULL) return NULL; used=0; write_start=last->mem; remain=asize; asize*=2; goto write;}else{last->used += len; mc->blocks_used+=len;log("use_mem_chain %d bytes : \n%s", len, write_start);}return write_start;}}

作者寄语

以上如有错漏之处,敬请大家指正。我是主修C/C++、Vue3,开发网站的程序员,我的联系方式:
微信:TobeBuda
Email/Paypal: jinmin.si@outlook.com
邀请您加入「社区资讯服务」创业微信群,共同探讨打造社区资讯服务的美好未来。

参考资料

chatgpt

gemini

mistral

claude

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【C语言】解决C语言报错:Dangling Pointer

文章目录 简介什么是Dangling PointerDangling Pointer的常见原因如何检测和调试Dangling Pointer解决Dangling Pointer的最佳实践详细实例解析示例1&#xff1a;释放内存后未将指针置为NULL示例2&#xff1a;返回指向局部变量的指针示例3&#xff1a;指针悬空后继续使用示例4&…

引领未来:AI Native与物联网(IoT)的革命性融合

引领未来&#xff1a;AI Native与物联网(IoT)的革命性融合 在数字化转型的浪潮中&#xff0c;AI Native作为一种新兴的软件开发模式&#xff0c;正逐渐成为推动技术创新的核心力量。与此同时&#xff0c;物联网(IoT)技术通过连接物理世界与数字世界&#xff0c;不断扩展其应用…

自编码器笔记

编码器解码器自编码器 先压缩特征&#xff0c;再通过特征还原。 判断还原的和原来的是否相等 encode data 在一个“潜在空间”里。它的用途是“深度学习”的核心-学习数据的特征并简化数据表示形式以寻找模式。 变分自编码器&#xff1a; 1. 首先、假设输入数据是符合正态分布…

tiny-redis 项目可能的问题

https://build-your-own.org/redis/ 事件循环怎么实现的 首先我将连接包装为一个 Connect 类&#xff0c;它包含了 socket fd&#xff0c;读写缓冲区&#xff0c;连接状态&#xff08;这个连接是发送数据还是接收数据&#xff09;等成员属性 我会在全局维护一个从 socket fd…

003 选择排序

文章目录 先挑最值&#xff0c;再把剩下的挑最值&#xff0c;再把剩下的挑最值。。。 -- 排序函数 function selectionSort(arr) -- 外层循环&#xff0c;从数组的第一个元素开始&#xff0c;对每个元素进行排序 for i 1, #arr do -- 假设当前位置的元素是最小的 local …

LCR 060. 前 K 个高频元素

给定一个整数数组 nums 和一个整数 k &#xff0c;请返回其中出现频率前 k 高的元素。可以按 任意顺序 返回答案。 示例 1: 输入: nums [1,1,1,2,2,3], k 2 输出: [1,2] 示例 2: 输入: nums [1], k 1 输出: [1] 提示&#xff1a; 1 < nums.length < 105k 的取值范…

【SQL Server点滴积累】Setup SQL Server 2008 Database Mirror (二)

【SQL Server点滴积累】Setup SQL Server 2008 Database Mirror (一)-CSDN博客今天分享SQL Server 2008 R2搭建数据库镜像(Database Mirror)https://blog.csdn.net/ncutyb123/article/details/139749117?spm1001.2014.3001.5501本篇Blog基于以上Blog步骤进行SQL Server 2008 R…

python03——文件操作(new)

“变量”open&#xff08;‘文件路径’&#xff0c;‘模式’&#xff09; //注意加引号 “变量”.write( ) //write函数是写的是字符串&#xff0c;如果你写的东西不是字符串&#xff0c;要写成write&#xff08;str&#xff08;。。&#xff09;&#xff09; “变量”.read…

vue3学习教程第四十节(pinia的用法注意事项解构store)

pinia 主要包括以下五部分&#xff0c;经常用到的是 store、state、getters、actions 以下使用说明&#xff0c;注意事项&#xff0c;仅限于 vue3 setup 语法糖中使用&#xff0c;若使用选项式 API 请直接查看官方文档&#xff1a; 一、前言&#xff1a; pinia 是为了探索 vu…

03_意向锁

意向锁&#xff08;Intention Lock&#xff09; 文章目录 意向锁&#xff08;Intention Lock&#xff09;简介类型原理意向锁加锁流程锁兼容矩阵使用场景示例总结扩展&#xff1a;意向锁和共享锁排他锁的加锁流程假设的场景和前提已加锁的情况新的加锁请求加锁流程锁的兼容性矩…

力扣算法-9.回文数

9.回文数 个人思考 首先从示例2可以看出符号也算在整数这个整体内&#xff0c;可以先判断整数若为负数则返回false其次很容易就会想到遍历两次&#xff0c;从头以及从尾&#xff0c;遍历得到的结果相比较&#xff0c;相同则为回文数 public class Alee9 {public static void …

OpenResty的安装及高级使用

OpenResty的安装及高级使用 1. OpenResty的安装1.1. 二进制版本安装1.2. 源码方式安装2. 日志打印header和body3. 替换body体字符串1. OpenResty的安装 OpenResty的中文站点:https://openresty.org/cn/    OpenResty的英文站点:https://openresty.org/en/ 1.1. 二进制版本…

【linux基础】后台执行命令,防止中断nohup

前台运行与后台运行&#xff1a;前台运行&#xff0c;就是运行过程一直在屏幕输出。 目的&#xff1a;1. 提交至后台 & 2.防止中断 nohup 1.终端上不要有大量的log出现&#xff0c;后台运行 (1) & 程序后台运行 #脚本、修改权限 vi test.sh chmod 777 test.sh#后…

ArcGIS Pro SDK (三)Addin控件 3 事件功能类

22 ArcGIS Pro 放置处理程序 目录 22 ArcGIS Pro 放置处理程序22.1 添加控件22.2 Code 23 ArcGIS Pro 构造工具23.1 添加控件23.2 Code 24 ArcGIS Pro 表构造工具24.1 添加控件24.2 Code 22.1 添加控件 22.2 Code 放置处理程序可以实现文件拖动放置、TreeVIew、ListBox等控件拖…

极速安装的艺术:使用 Mamba 革新你的 Conda 环境管理

标题&#xff1a;极速安装的艺术&#xff1a;使用 Mamba 革新你的 Conda 环境管理 引言 在数据科学和机器学习领域&#xff0c;Conda 是一个广受欢迎的包管理器和环境管理器。然而&#xff0c;随着项目规模的增长&#xff0c;Conda 在处理大量依赖时可能会显得缓慢。Mamba&am…

水下机器人ArduSub 固件常用参数

目前最新版的ArduSub 固件是4.1.2&#xff0c;本文的参数是基于这个版本的固件 SURFACE_DEPTH&#xff1a;水表深度读数 当水下机器人在水面时&#xff0c;水压传感器将读取的深度数据&#xff08;以厘米为单位&#xff09;&#xff0c;这个相当于抵消零偏 单位&#xff1a;…

ArcGIS批量设置多图层的三调地类符号

​​ 点击下方全系列课程学习 点击学习—>ArcGIS全系列实战视频教程——9个单一课程组合系列直播回放 01需求说明 这次我们要实现的是将多个地类图层批量符号化。比如将多个三调地类图斑批量符号化。 ​ 有什么好方法呢 &#xff1f; 我们可以将一个图层利用三调符号库进行…

android 从应用中打开第三方应用

打开第三方应用之前需要先判断该应用是否存在&#xff0c;代码如下&#xff1a; public boolean isAppInstalled(Context context, String packageName) {PackageManager packageManager context.getPackageManager();try {packageManager.getPackageInfo(packageName, Packa…

Stable Diffusion 3 正式开源,超强文生图模型 SD3-M 上线,赶紧来试试吧!

前言 我们都知道 Stable Diffusion 3 是一款强大的文生图模型&#xff0c;拥有20亿参数&#xff0c;因其高效的推理速度和卓越的生成效果而备受瞩目。 近日&#xff0c;Stability AI在推特上宣布正式开源了 Stable Diffusion 3 Medium&#xff08;SD3-M&#xff09; 权重&…

Dooprime外汇:如何高效规划家庭理财?从哪里开始?

摘要&#xff1a; 家庭理财是每个家庭都必须面对的重要课题。合理的理财规划不仅能提高家庭的生活质量&#xff0c;还能为未来的生活提供保障。然而&#xff0c;许多人在面对复杂的理财选项和信息时感到无从下手。本文将从不同角度详细分析如何进行高效的家庭理财规划&#xf…