malloc分配一维数组 动态分配数组大小问题

C中 malloc()分配堆内存实际的大小 - 博客频道 - CSDN.NET
读书就是慢慢地将书里书外想个遍。
分类:-[小西南]-
以前相关笔记:、。
C动态分配的实际大小
Figure1:内存中的堆内存空间
假设从《The &C &Programming &Language》中推测正确,从未经动态分配的堆内存呈现上图形式。不连续的堆内存以“链”的形式联系:Heap1 -& Heap2 -&Heap3 -&Heap4-&Heap1。笔记将构成“堆链”的每个堆内存(如Heap1)称为“堆块”。malloc()/free()将每个堆块看作由两部分构成:“Header”和“可用堆内存”。在Header中包含了“指向下一个堆内存块的指针”、“本堆块的大小”。这样malloc()/free()就能更好地管理堆。
2 堆内存分配
[1] mallco()分配机制
根据C中malloc(n)函数动态分配堆的机制:分配堆内存的时候就依序由低到高的地址搜索“堆链”中的堆块,搜索到“可用堆内存”满足n的堆块(如Heap1)为止。若Heap1的“可用堆内存”刚好满足n,则将Heap1从“堆链”中删除,同时重新组织各堆块形成新的“堆链”;若Heap1的“可用堆内存”大小大于n,则将malloc(n)申请到的“Header” + &可用堆内存&部分从Heap1中分裂,将剩余的Heap1堆内存块重新加入“堆链”中。经分裂后的堆内存也包含“Header”和“可用堆内存”两部分(如图Figure
2),然后将由malloc()分配得到的“可用堆内存”返回给用户。若某块堆内存空间比较大(如Heap1),能够满足较小内存的多次申请,那么由malloc(n)多次申请的堆内存块都是连续被分配给用户的(因为有Header,所以用户使用的堆地址不连续)。
为方便free()释放堆空间,经malloc(n)分配给用户的堆空间也隐含一个Header。如下图所示:
Figure2:malloc()分配的堆内存结构
由于Header的构成的内存对齐,C中malloc(n)函数分配的堆内存会大于等于Header + n。
[2] 程序验证
为了测试C语言malloc()函数所分配堆的实际大小(Header 大小和内存对齐),编写了如下宏:
#define malloc_no_free(type, type_str)
printf(&%s\tsizeof(%s)=%d\t&, type_str, type_str, sizeof(type));\
type *pthis = NULL, *plast = NULL;
for(i = 0; i & 6; ++i){
if( NULL != (pthis = (type *)malloc(sizeof(type))) ){
printf(&%d\t&, (int)pthis - (int)plast);\
plast =/*a litte logic to p*/
/*free(pthis);*/
pthis = NULL;
printf(&\n\n&);
用宏写这一段函数式为了在C中能够传递任何数据类型的变量。如果传递给malloc()函数的参数较小,那么malloc()函数是极有可能在图中的Heap1对区域进行多次分配的,如此这段代码就能够测试出malloc()函数分配堆内存的实际大小。
将此宏在主函数中调用:
struct _sc{ };
struct _sic{ };
struct _sip{ struct _sip *p; };
struct _sdc{};
struct _s17{ char a[17]; };
int main()
malloc_no_free(char, &char&);
malloc_no_free(int, &int&);
malloc_no_free(double, &double&);
malloc_no_free(struct _sc, &_sc&);
malloc_no_free(struct _sic, &_sic&);
malloc_no_free(struct _sip, &_sip&);
malloc_no_free(struct _sdc, &_sdc&);
malloc_no_free(struct _s17, &_17&);
在codeblocks + GNU GCC compiler下编译通过并运行得到一下结果:
Figure3:程序运行结果
分析运行结果:
(1) 如果将宏中” free(pthis);”的注释去掉,则所有的地址差都为0。这恰好验证了free()堆地址的机制:假设将要被释放的堆内存的地址为p,free(p)将以p为首地址的堆内存块释放到堆链中的某个地址上,且此地址跟p值最邻近,这样就可以保证尽可能的使堆内存以大块的形式存在而不至于让堆内存成为碎片。
(2) 将” free(pthis);”注释
各结构体所占内存大小再一次体现了。在一大块堆之上用malloc()函数分配内存,真实得到的内存要比实际大。得到的真实内存块的大小为8(实为内存对齐大小值)的整数倍。当数据结构所占内存为16的倍数时,malloc()分配的内存会多出8个字节,这8个字节就是header。(将struct _s17内数组维数改为16倍数时可验证)。
从这里可以看出:Header所占堆内存大小为8字节,堆内存对齐也为8(会看内存对齐就不难观察出来)。
3 动态分配内存对齐
造就实际分配内存大于用户所需原因:
每次malloc(n)分配的堆内存由Header + n构成。Header造就的内存对齐。
[1] Header
在的第八章”The& UNIX System Interface”的第七节”Example – A Strorage Allocator”中用以下结构体描述了Header:
typedef long A
union header {
union header *
union &header用其成员s.ptr作为指向堆链表中下一个堆块,s.size保存此堆的大小。x本意是用于内存对齐。malloc()/free()就是通过以堆内存为存储空间隐藏于用户的Header结构体来合理地管理堆内存的。
[2] 内存对齐
《C圣经》中想用Align(long)作为内存对齐的值,但由于win32上sizeof(long) = 4,由于sizeof(union header) = sizeof(s) = 8,故而在malloc()返回的堆内存中存储数据的内存对齐数值为8。
所以,以上为每种数据类型所分配堆空间实际大小就得到了合理的解释(排除第一个为32 bytes):
Figure4:C中实际的动态分配
所以在适当的明白malloc()的实际分配之后,在以后程序中的动态分配过程中就要利用这个过程避免堆内存的浪费:许多单独的堆内存块可以合并在一起分配,这样程序在运行过程中使用的堆内存会减少,有利于程序压缩空间。
4 malloc()分配总结
对于C中的malloc(n)分配,有以下进一步的结论:
实际分配的堆内存是Header + n结构。返回给用户的是n部分的首地址。由于内存对齐值8,实际分配的堆内存大于等于sizeof(Header) + n。
所以在编程过程中,需要用内存对齐的知识合理的让malloc()分配的内存变得小一些。
C Note Over。
排名:第541名
(3)(424)2016年10月优秀大版主2016年8月优秀大版主
2016年9月 总版技术专家分月排行榜第二
2016年10月优秀大版主2016年8月优秀大版主
2016年9月 总版技术专家分月排行榜第二
2013年 总版技术专家分年内排行榜第三
2012年 总版技术专家分年内排行榜第七
2013年 总版技术专家分年内排行榜第三
2012年 总版技术专家分年内排行榜第七
匿名用户不能发表回复!|
每天回帖即可获得10分可用分!小技巧:
你还可以输入10000个字符
(Ctrl+Enter)
请遵守CSDN,不得违反国家法律法规。
转载文章请注明出自“CSDN(www.csdn.net)”。如是商业用途请联系原作者。查看: 516|回复: 9
内存管理的几个问题,先定义一个大数组,在用malloc给其他变量分配内存,会有地址重叠的情况吗?
主题帖子精华
初级会员, 积分 178, 距离下一级还需 22 积分
在线时间40 小时
关于内存管理的问题,例如:已经先定义一个大数组 : u32 a[1024],然后再用内存管理给指针P分配2K内存 :p=mymalloc(sramx,2048);
1、数组a在RAM上的地址空间会出现与p的重叠吗?
2、p可以用myfree(sramx,p)释放内存,数组a[1024]能释放内存吗?
3、既然数组a是占用ram空间的,my_mem_perused(SRAMIN)是没有计算到数组a的占用的空间的?这样合理吗?
请大神指教!!!
1,不会。2,不行。3,为什么不合理?
主题帖子精华
金钱111082
在线时间779 小时
1,不会。2,不行。3,为什么不合理?
主题帖子精华
初级会员, 积分 178, 距离下一级还需 22 积分
在线时间40 小时
数组a定义时,不是没有在内存管理表做标记吗;那用my_mem_perused(SRAMIN)计算的值就不包括数组a占用的内存啦。
主题帖子精华
初级会员, 积分 178, 距离下一级还需 22 积分
在线时间40 小时
1,不会。2,不行。3,为什么不合理?
数组a定义时,不是没有在内存管理表做标记吗;那用my_mem_perused(SRAMIN)计算的值就不包括数组a占用的内存啦。
主题帖子精华
金牌会员, 积分 1604, 距离下一级还需 1396 积分
在线时间182 小时
数组在栈里面,自上往下增长;内存管理在堆里面,自下往上增长。
态度决定一切 四人行
主题帖子精华
初级会员, 积分 178, 距离下一级还需 22 积分
在线时间40 小时
数组在栈里面,自上往下增长;内存管理在堆里面,自下往上增长。
就是说当这两个占用的内存达到一度程度时,是会出现重叠交叉的情况咯?
主题帖子精华
金牌会员, 积分 1604, 距离下一级还需 1396 积分
在线时间182 小时
就是说当这两个占用的内存达到一度程度时,是会出现重叠交叉的情况咯?
很难,栈在启动文件里面已经定义大小了,一般不会超过1-2K。
态度决定一切 四人行
主题帖子精华
金钱111082
在线时间779 小时
数组a定义时,不是没有在内存管理表做标记吗;那用my_mem_perused(SRAMIN)计算的值就不包括数组a占用的内存 ...
当然不包括。
内存管理又没说要全部内存都用作管理。它只是管理大部分内存而已。全局变量什么的,和内存管理无关。
我是开源电子网站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺:
微信公众平台:正点原子& &
主题帖子精华
初级会员, 积分 178, 距离下一级还需 22 积分
在线时间40 小时
当然不包括。
内存管理又没说要全部内存都用作管理。它只是管理大部分内存而已。全局变量什么的,和内存 ...
哦。。明白
主题帖子精华
初级会员, 积分 178, 距离下一级还需 22 积分
在线时间40 小时
很难,栈在启动文件里面已经定义大小了,一般不会超过1-2K。
好的。谢谢!
Powered by

我要回帖

更多关于 malloc动态分配内存 的文章

 

随机推荐