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.pswp.cn/diannao/35098.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/35098.shtml
英文地址,請注明出處:http://en.pswp.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…