c语言动态c语言指针分配内存存的问题,新手,求大神

C语言动态内存管理
动态存储管理的基本问题是:如何按请求分配内存,如何回收内存再利用。提出请求的用户可能是系统的一个作业,也可能是程序中的一个变量。
未曾分配的地址连续的内存区称为&空闲块&。
已分配给用户使用的地址连续的内存区称为&占用块&。
系统刚刚启动时,整个内存可看做一个大的&空闲块&,随着用户请求的进入,系统依次分配相应的内存。
在系统运行过程中,内存被分为两大部分:低地址区(若干占用块)和高地址区(空闲块)。
经过一段时间后,有的程序运行结束,释放掉它所占用的内存,使之变为空闲块,这就使整个内存中空闲块和占用块之间出现了相互交错的现象。如下图:
当系统进入到图中b),又有新的用户请求分配内存时,系统该如何处理呢?
方法一:系统继续从高地址区的空闲块进行分配,直到无法分配。当剩余的空闲块不能满足分配请求时,系统才去回收所有的不再使用的内存区,并重新组织内存,紧凑所有的空闲块为一个大的空闲块,以备在分配。
方法二:空闲链表。空闲链表中包含了所有空闲块的信息,一个节点对应一个空闲块。当用户请求分配时,系统所作的工作就是搜索空闲链表,按某种策略找到一个合适的空闲块进行分配,并删除对应的节点。当用户释放所占用的内存时,系统回收该内存,并将它插入到空闲链表中。
空闲链表三种结构形式:
(1)所有请求的内存大小相同。这是一种最简单的动态存储管理方式。
对此,系统通常的做法是:
a)系统启动时,将内存按大小均分成若干个块,并形成一个链表。
b)分配时,只需将链表中第一个节点分配给用户即可,无需扫描整个链表。
c)回收时,将空闲块插入到链表头即可。
(2)所有请求的内存大小有n种规格。可创建n个(1)情况中的链表,分配与回收与(1)类似,不同之处在于:当请求的链表为空时,需要在节点大的链表上进行分配,取一部分内存给用户,剩余部分作为一个新节点插入到相应的链表中。
(3)所有请求的内存大小是不同的,是不断发生变化的。这种情况下的分配与回收见下篇。
分配算法和回收
对于内存块大小不同的空闲链表,假如有一个大小为N的内存申请,如果空闲链表中大于N的内存只有一块,假如大小为M,就把M的一部分分配给用户,同时把剩余的M-N的部分作为一个节点插入到空闲链表中。
当大于N的内存有多块时,我们该如何分配呢?通常有以下三种方法:
(1)最先适配法。顾名思义,顺序扫描空闲链表,找到第一个大于等于N的空闲块,把其中的N分配给用户。因为链表不按内存的地址有序,也不按大小有序,所以回收内存块放到表头即可。
问题:运行一段时间后,链表中将会出现一些非常小的块,并在这些小块都在链表的前边。
(2)最优适配法。在空闲链表中找到一个不小于N并且最接近N的空闲块分配给用户。分配时需要整表扫描。如果链表按空闲块从小到大有序,分配时只需找到第一个大于N的空闲块,回收时需要插入到链表合适的位置上。
(3)最差适配法。将链表中不小于N且是链表中最大的空闲块的一部分分配给用户。链表可按空闲块从大到小的顺序排列,分配只需判断链表第一个空闲块即可,回收时需要插入到链表合适的位置上。
对于回收,我们考虑的不仅仅是归还节点,还要考虑空闲块的合并问题。这种把物理地址相邻的空闲块的合并以取得更大的空闲块的方法是需要的。空闲链表中的空闲块并不是按物理地址有序的,那又如何快速合并呢?下篇中将讨论一种方法:边界标识法
边界标识法
原文链接:https://blog.csdn.net/hbuxiaoshe/article/details/5994743
就空闲链表来说,要确定哪些空闲块是物理地址相邻的,确实不太容易,需要整表扫描。
边界标识法能够有效的判断空闲块的物理相邻内存块是否为空闲块。
所有的空闲块组成一个双向循环链表,链表中每一个节点的结构如下:
llink和rlink分别指向链表中的前驱后继节点。
size表明内存块的大小。
uplink指向本块的首地址,图中箭头,其作用下面讲述。
tag头和尾中各有一个,作为内存块边界的标识,0表空闲块,1表占用块。
分配时同样会在链表上产生很多非常小的空闲块,影响分配的效率,因此,可以定义一个全局的指针p,当不为空时分配,使其始终指向刚进行过分配的节点的后继节点。
回收时判断物理相邻的块是否为空闲块的方法:
假设当前回收块的物理地址为p(下面涉及到的左邻块和右邻块都是物理地址相邻的,在循环链表中也许不相邻),
左邻块:左邻块的尾的地址是p1=p-sizeof(尾),左邻块是否为空闲块的判断则为p1-&tag是否为0。当为空闲块时,只需将当前块合并到左邻块中即可,而左邻块的地址则需要由uplink来获得(原因是中间内存块的大小是不固定的,不能通过偏移来实现),即p1-&uplink。修改左邻块的size和uplink即可。
右邻块:右邻块的首的地址为p2=p+sizeof(头),右邻块是否为空闲块的判断则为p2-&tag是否为0。当为空闲块时,与右邻块合并,修改p的llink、rlink和size,修改p2的uplink。
你可能会认为,既然链表中的块都是空闲块,干吗还要加上tag标识位呢?我的回答是,如果没有tag,当我们找到右邻块的地址时,没有办法判断右邻块是不是链表中的一个节点,也许它还在被用户使用着。那为什么要用两个tag呢?个人觉得,用一个也可以,但用两个更容易判断。博客访问: 664838
博文数量: 259
博客积分: 10081
博客等级: 上将
技术积分: 2585
注册时间:
IT168企业级官微
微信号:IT168qiye
系统架构师大会
微信号:SACC2013
分类: C/C++ 23:06:57
阅读(7092) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~
请登录后评论。c语言中什么是动态分配内存?_百度知道
c语言中什么是动态分配内存?
我有更好的答案
c语言用函数malloc动态分配内存的,要用到指针,释放内存是free指针malloc
原型:extern void *malloc(unsigned int num_bytes);
用法:#include &malloc.h&
或#include&stdlib.h&
功能:用于向内存申请空间,分配长度为num_bytes字节的内存块
说明:如果分配成功则返回指向被分配内存的指针,否则返回空指针NULL。
当内存不再使用时,应使用free()函数将内存块释放。
调用格式,
指针名=(指针所指对象的数据类型*)malloc(个数*sizeof(指针所指对象的数据类型)),其对应例子如下:
int *p = (int *) malloc ( n* sizeof(int) );
// malloc.c
#include &syslib.h&
#include &malloc.h&
clrscr(); // clear screen
p=(char *)malloc(100);
printf(&Memory Allocated at: %x&,p);
printf(&Not Enough Memory!\n&);
getchar();
参考资料:
采纳率:33%
#include &malloc.h&
if( (buffer = (long *)malloc( 1000 * sizeof( long ) )) == NULL )
exit( 1 );
size = _msize( buffer );stdio.h&void main( void ){
size = _msize( buffer );
printf( &n&;
if( (buffer = realloc( buffer, size + (1000 * sizeof( long )) ))
exit( 1 ), size );* Reallocate and show new size: */
printf( &Size of block after malloc of 1000,
free( buffer );
exit( 0 ).h&#include &MSDN里面的例子#include &Size of block after realloc of 1000 more longs: %u\n&quot: %u&#92relloc()
为您推荐:
其他类似问题
您可能关注的内容
动态分配内存的相关知识
换一换
回答问题,赢新手礼包
个人、企业类
违法有害信息,请在下方选择后提交
色情、暴力
我们会通过消息、邮箱等方式尽快将举报结果通知您。C语言动态数组与内存分配,calloc与malloc的区别_zero程序猿_新浪博客
C语言动态数组与内存分配,calloc与malloc的区别
C语言中如何实现动态数组:
​方法一:
int array[n];
方法二:
p=(int*)malloc(n*sizeof(int));
p1=(int*)calloc(n,sizeof(int));​
二维数组:
int (*p2)[6];//在c99之前可以使用
p2=(int (*)
[6])malloc(n*6*sizeof(int));​//n*6的数组
int (*p3)[col] = (int
(*)[])malloc(row*col*sizeof(int));//要求变长数组支持,在c90是不可以用的,c99可以使用
malloc与calloc区别:​
malloc,calloc和free都在中
C语言分配内存有三种方式:
1.静态分配:在程序运行之前就已经分配好(编译阶段),例如全局变量,static变量。当整个程序结束时销毁。
2.栈的分配:在程序​运行中,分配栈内存给函数的局部变量,当这段函数运行结束时自动释放。例如auto变量。栈内存分配运算内置于处理器的指令集中,效率很高,但是分配的内存容量有限。
3.​动态分配:在程序运行时,有程序员代码决定内存的分配和释放。用free释放,注意内存泄漏。当程序结束时,也会全部释放内存。优点:灵活。缺点:动态分配过程中,可能使内存碎片化,从而导致进程比使用栈内存而慢。
malloc(要分配内存的大小以字节计算),在ANSI之前版本,返回一个char。在ANSIC中返回void指针,如果没有找到内存可以分配返回NULL指针​​。​
void calloc(内存单元的数量,每个单元的大小以字节计算);​
在ANSI之前版本,返回一个char指针,在ANSI返回一个void指针​​​
分配成功的指针指在所分配内存的起始处。
他们的主要区别是:​​
calloc会对分配的内存进行初始化,块中的全部位置设置为零。(在某些系统中,浮点数0的初始值,并不是全部用0来表示的)。​​
realloc有个细节需要注意:
无非就是将已经存在的一块内存扩大。
char* p = malloc(1024);
char* q = realloc(p,2048);
现在的问题是我们应该如何处理指针 p。 刚开始按照我最直观的理解,如果就是直接将 p = NULL;。 到最后只需要释放
q的空间就可以了。
因为最近在做个封装。结果在做单元测试的时候发现。有时候我在 free(q); 的时候会出错。这样我就郁闷了。
后来仔细一跟踪,发现 realloc 完以后 q 和 p 的指针地址是一样。不过有时候又不一样。
仔细查了下资料。得到如下信息:
1.如果 当前连续内存块足够 realloc 的话,只是将p所指向的空间扩大,并返回p的指针地址。 这个时候 q 和 p
指向的地址是一样的。
&&&&&&&2.如果
当前连续内存块不够长度,再找一个足够长的地方,分配一块新的内存,q,并将 p指向的内容 copy到 q,返回
q。并将p所指向的内存空间删除。
这样也就是说 realloc 有时候会产生一个新的内存地址 有的时候不会。所以在分配完成后。我们需要判断下 p 是否等于
q。并做相应的处理。
这里有点要注意的是要避免 p = realloc(p,2048); 这种写法。有可能会造成 realloc
分配失败后,p原先所指向的内存地址丢失。​
zero程序猿
博客等级:
博客积分:0
博客访问:1,844
关注人气:0
荣誉徽章:3被浏览479分享邀请回答13 条评论分享收藏感谢收起04 条评论分享收藏感谢收起写回答

我要回帖

更多关于 c语言指针分配内存 的文章

 

随机推荐