mallco动态分配_malloc动态分配的内存的生存周期是多少?

malloc与new的内存管理机制
博客探讨了malloc和new在动态分配内存时如何处理内存大小信息,以及free和delete如何在没有明确大小的情况下正确释放内存。malloc可能在分配的内存前存储大小信息,而new则为每个内存区域配置额外的DWORD来保存元素数量。文章通过示例代码解释了这个过程,并警告修改这些额外信息可能导致内存释放问题。

曾经有一个朋友提过这样一个问题,malloc动态分配的内存的生存周期是多少当时直接回答,当然是在调用free进行释放之前阿!!但回头我仔细想过这个问题,在free调用之前那段范围内,但free只有一个指针参数,它是如何知道要释放多少空间呢比如:

int*pInt=(int*)malloc(10*sizeof(int));

…….;

free(p);

这里free是如何知道释放10个int大小的空间呢既然free只需要一个参数—指针类型,那么这个地址(malloc返回的)一定作过什么特殊处理了.于是我问了一些网上的朋友,我得出以下一些结果:

char*p=malloc(size):

1. 实际分配一块size + 4大小的内存,char *p = 内存首地址。

2. *((int *)p) = size; //把大小放在分配内存的起始处。

3. return (void*)(p + 4); //返回除去存放大小以后的部分。

free(p); 1. char* q = (char *)p - 4;

2. int size = *((int *)q); //这里找到了size...

3. 通过操作系统释放内存或自己管理C/C++堆内存.

这里要涉及到一些OS管理内存得问题,非我力所能及,但我们可以知道,malloc确实实施了一些特殊的处理.言归正传.让我们看看下面一段c++代码:

int*p=new int;

delete []p;

一眼就看出上面得代码完成的和上面的c代码一样的功能.这里有同样的问题,为什么delete

能在不指定动态分配的数组size下就能释放所分配的对象呢,是不是new操作也对返回的地址作了一些手脚?答案:是.new所作的处理和上面的方法一样的,即:new所传回的每一个内存区域配置一个额外的DWORD,然后把元素数目包藏到那个DWORD中.(不是所有编译器都采用这个方法的,我只试过vc6和bcc55编译器,它们都采用这个方法.不过,

#ifndef __MALLOC_H #define __MALLOC_H #include "stm32f10x.h" // 内存池定义:STM32F103C8T6只有内部RAM(20KB),不包含外部RAM #define SRAMIN 0 // 内部内存池编号 #define SRAMBANK 1 // 内存池数量(仅使用1个) // 内存管理参数调整(适配C8T6的20KB RAM) #define MEM1_BLOCK_SIZE 32 // 内存块大小设为32字节(提高小内存分配效率) #define MEM1_MAX_SIZE 12 * 1024 // 分配给内存管理的最大内存(12KB,保留8KB给堆栈和系统) #define MEM1_ALLOC_TABLE_SIZE (MEM1_MAX_SIZE/MEM1_BLOCK_SIZE) // 管理表大小 // 内存管理设备结构体 struct _m_mallco_dev { void (*init)(u8); // 初始化函数指针 u8 (*perused)(u8); // 内存使用率计算函数指针 u8 *membase[SRAMBANK]; // 内存池基地址数组 u16 *memmap[SRAMBANK]; // 内存池管理表基地址数组 u8 memrdy[SRAMBANK]; // 内存池初始化状态标志 }; extern struct _m_mallco_dev mallco_dev; // 声明全局内存管理设备 // 用户接口函数声明 void myfree(u8 memx, void *ptr); // 释放内存(外部调用) void *mymalloc(u8 memx, u32 size); // 分配内存(外部调用) u8 my_mem_perused(u8 memx); // 获取内存使用率(外部调用) #endif#include "malloc.h" #include <string.h> // 内部内存池(32字节对齐,便于DMA操作) __align(32) u8 mem1base[MEM1_MAX_SIZE]; // 内存管理表(记录每个内存块的状态) u16 mem1mapbase[MEM1_ALLOC_TABLE_SIZE]; void my_mem_init(u8 memx); u8 my_mem_perused(u8 memx); // 内存管理参数常量数组 const u32 memtblsize[SRAMBANK] = {MEM1_ALLOC_TABLE_SIZE}; // 管理表大小 const u32 memblksize[SRAMBANK] = {MEM1_BLOCK_SIZE}; // 内存块大小 const u32 memsize[SRAMBANK] = {MEM1_MAX_SIZE}; // 内存池总大小 // 全局内存管理设备实例 struct _m_mallco_dev mallco_dev = { my_mem_init, // 指向初始化函数 my_mem_perused, // 指向内存使用率函数 {mem1base}, // 内存池基地址(仅内部内存) {mem1mapbase}, // 内存管理表基地址 {0} // 初始化状态(0=未初始化) }; // 内存复制函数(内部使用) void mymemcpy(void *des, void *src, u32 n) { u8 *xdes = des; u8 *xsrc = src; while(n--)*xdes++=*xsrc++; // 逐字节复制 } // 内存设置函数(内部使用) void mymemset(void *s, u8 c, u32 count) { u8 *xs = s; while(count--)*xs++=c; // 逐字节设置 } // 内存池初始化(内部调用) void my_mem_init(u8 memx) { // 清零内存管理表(初始化所有块为空闲) mymemset(mallco_dev.memmap[memx], 0, memtblsize[memx]*2); // 标记内存池已初始化 mallco_dev.memrdy[memx]=1; } // 获取内存池使用率(内部调用) u8 my_mem_perused(u8 memx) { u32 used=0; // 遍历管理表,统计已用块数 for(u32 i=0;i<memtblsize[memx];i++) { if(mallco_dev.memmap[memx][i])used++; } // 计算并返回使用百分比 return (used*100)/(memtblsize[memx]); } // 内存分配核心算法(内部调用) u32 my_mem_malloc(u8 memx,u32 size) { signed long offset=0; u32 nmemb; // 需要的内存块数 u32 cmemb=0; // 当前找到的连续空闲块数 // 检查内存池是否初始化 if(!mallco_dev.memrdy[memx])mallco_dev.init(memx); // 计算需要的内存块数(向上取整) nmemb=size/memblksize[memx]; if(size%memblksize[memx])nmemb++; // 从内存池尾部向前搜索连续空闲块 for(offset=memtblsize[memx]-1;offset>=0;offset--) { if(!mallco_dev.memmap[memx][offset])cmemb++; // 空闲块计数 else cmemb=0; // 中断连续 // 找到足够的连续空闲块 if(cmemb==nmemb) { // 标记这些块为已分配(存储分配块数) for(u32 i=0;i<nmemb;i++) { mallco_dev.memmap[memx][offset+i]=nmemb; } return (offset*memblksize[memx]); // 返回偏移地址 } } return 0XFFFFFFFF; // 分配失败(内存不足) } // 内存释放(内部调用) u8 my_mem_free(u8 memx,u32 offset) { // 检查内存池是否初始化 if(!mallco_dev.memrdy[memx]) { mallco_dev.init(memx); return 1; // 返回未初始化错误 } // 检查偏移是否有效 if(offset<memsize[memx]) { // 计算块索引 int index=offset/memblksize[memx]; // 获取该块分配时记录的块数 int nmemb=mallco_dev.memmap[memx][index]; // 释放连续的内存块(标记为空闲) for(int i=0;i<nmemb;i++) { mallco_dev.memmap[memx][index+i]=0; } return 0; // 成功 } return 2; // 偏移超出范围 } // 释放内存(用户接口) void myfree(u8 memx,void *ptr) { if(ptr==NULL)return; // 空指针检查 // 计算偏移量(地址 - 基地址) u32 offset=(u32)ptr-(u32)mallco_dev.membase[memx]; my_mem_free(memx,offset); // 调用内部释放 } // 分配内存(用户接口) void *mymalloc(u8 memx,u32 size) { // 调用内部分配函数获取偏移 u32 offset=my_mem_malloc(memx,size); if(offset==0XFFFFFFFF)return NULL; // 分配失败 else return (void*)((u32)mallco_dev.membase[memx]+offset); // 返回绝对地址 }这些代码适合stm32f103c8t6使用嘛,能够分配内存
最新发布
07-16
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值