动态内存申请函数选择(realloc、malloc 、alloca、 calloc)

来源:互联网 发布:无线网络规划软件 编辑:程序博客网 时间:2024/06/09 19:44

1、函数realloc 

函数简介:

     原型:extern void *realloc(void *mem_address, unsigned int newsize);
     语法:指针名=(数据类型*)realloc(要改变内存大小的指针名,新的大小)。//新的大小一定要大于原来的大小,不然的话会导致数据丢失!
     头文件:#include <stdlib.h> 有些编译器需要#include <malloc.h>,在TC2.0中可以使用alloc.h头文件
     功能:先判断当前的指针是否有足够的连续空间,如果有,扩大mem_address指向的地址,并且将mem_address返回,如果空间不够,先按照newsize指定的大小分配空间,将原有数据从头到尾拷贝到新分配的内存区域,而后释放原来mem_address所指内存区域,同时返回新分配的内存区域的首地址。即重新分配存储器块的地址。
    返回值:如果重新分配成功则返回指向被分配内存的指针,否则返回空指针NULL。 
    注意:这里原始内存中的数据还是保持不变的。当内存不再使用时,应使用free()函数将内存块释放。
 
详细说明及注意要点:
 
    
       1、如果有足够空间用于扩大mem_address指向的内存块,则分配额外内存,并返回mem_address。
这里说的是“扩大”,我们知道,realloc是从堆上分配内存的,当扩大一块内存空间时, realloc()试图直接从堆上现存的数据后面的那些字节中获得附加的字节,如果能够满足,自然天下太平。也就是说,如果原先的内存大小后面还有足够的空闲空间用来分配,加上原来的空间大小= newsize。那么就ok。得到的是一块连续的内存。
      2、如果原先的内存大小后面没有足够的空闲空间用来分配,那么从堆中另外找一块newsize大小的内存。
并把原来大小内存空间中的内容复制到newsize中。返回新的mem_address指针。(数据被移动了)。
老块被放回堆上。
    
例如:#include <malloc.h>void main(){   char *p,*q;   p = (char * ) malloc (10);   q=p;   p = (char * ) realloc (q,20); //A   …………………………}
     在这段程序中我们增加了指针q,用它记录了原来的内存地址p。这段程序可以编译通过,但在执行到A行时,如果原有内存后面没有足够空间将原有空间扩展成一个连续的新大小的话,realloc函数就会以第二种方式分配内存,此时数据发生了移动,那么所记录的原来的内存地址q所指向的内存空间实际上已经放回到堆上了!这样就会产生q指针的指针悬挂,即指针指向了一块没有分配给用户使用的内存,如果再用q指针进行操作就可能发生意想不到的问题。所以在应用realloc函数是应当格外注意这种情况。

     3、返回情况
     返回的是一个void类型的指针:调用成功。(这就要求在你需要的时候进行强制类型转换
     返回NULL:当需要扩展的大小(第二个参数)为0并且第一个参数不为NULL时。此时原内存变成“freed(游离)”的了。
   返回NULL:当没有足够的空间可供扩展的时候。此时,原内存空间的大小维持不变。
4、特殊情况
      如果mem_address为NULL,则realloc()和malloc()类似。分配一个newsize的内存块,返回一个指向该内存块的指针
     如果newsize大小为0,那么释放mem_address指向的内存,并返回NULL。
     如果没有足够可用的内存用来完成重新分配(扩大原来的内存块或者分配新的内存块),则返回NULL。而原来的内存块保持不变。
 
realloc使用总结:
 
     1. realloc失败的时候,返回NULL
    2. realloc失败的时候,原来的内存不改变,不会释放也不会移动
    3 . 假如原来的内存后面还有足够多剩余内存的话,realloc的内存=原来的内存+剩余内存,realloc还是返回原来内存的地址; 假如原来的内存后面没有足够多剩余内存的话,realloc将申请新的内存,然后把原来的内存数据拷贝到新内存里,原来的内存将被free掉,realloc返回新内存的地址
    4. 如果size为0,效果等同于free()。这里需要注意的是只对指针本身进行释放,例如对二维指针**a,对a调用realloc时只会释放一维,使用时谨防内存泄露
    5. 传递给realloc的指针必须是先前通过malloc(),calloc(), 或realloc()分配的
    6.传递给realloc的指针可以为空,等同于malloc
 
2、alloca()函数
     函数简介
     内存分配函数,与malloc,calloc,realloc类似,但是注意一个重要的区别,_alloca是在栈(stack)上申请空间,用完马上就释放,包含在头文件malloc.h中,在某些系统中会宏定义成_alloca使用。
    函数原型
void * __cdecl  alloca(size_t);
 
注意事项
       在调用 alloca的函数返回的时候, 它分配的内存会自动释放。也就是说, 用 alloca 分配的内存在栈上。
alloca不具可移植性, 而且在没有传统堆栈的机器上很难实现。当它的返回值直接传入另一个函数时会带来问题,因为他分配在栈上.由于这些原因,alloca不宜使用在必须广泛移植的程序中, 不管它可能多么有用。
int main(){    int *p = (int *)alloca(sizeof(int)*10);    free(p);//此时不能用free()去释放,会导致错误     return 0;}

3 、calloc函数
    函数简介
   
     calloc是一个C语言函数
     函数名: calloc
     void *calloc(unsigned n,unsigned size);
     功 能: 在内存的动态存储区中分配n个长度为size的连续空间,函数返回一个指向分配起始地址的指针;如果分配不成功,返回NULL。
     跟malloc的区别:
     calloc在动态分配完内存后,自动初始化该内存空间为零,而malloc不初始化,里边数据是随机的垃圾数据。并且malloc申请的内存可以是不连续的,而calloc申请的内存空间必须是连续的。
#include <stdlib.h>#include<string.h>#include <stdio.h>int main(void){    char *str = NULL;    /* 分配内存空间 */    str = (char*)calloc(10, sizeof(char));    /* 将hello写入*/    strcpy(str, "Hello");    /*显示变量内容*/    printf("String is %s\n", str);    /* 释放空间 */    free(str);    return 0;}
4、malloc函数
      函数简介
原型:extern void *malloc(unsigned int num_bytes);
    
    功能:分配长度为num_bytes字节的内存块
     返回值:如果分配成功则返回指向被分配内存的指针(此存储区中的初始值不确定),否则返回空指针NULL。当内存不再使用时,应使用free()函数将内存块释放。函数返回的指针一定要适当对齐,使其可以用于任何数据对象
    说明:关于该函数的原型,在旧的版本中malloc返回的是char型指针,新的ANSIC标准规定,该函数返回为void型指针,因此必要时要进行类型转换。
 
函数的工作机制
       malloc函数的实质体现在,它有一个将可用的内存块连接为一个长长的列表的所谓空闲链表。调用malloc函数时,它沿连接表寻找一个大到足以满足用户请求所需要的内存块。然后,将该内存块一分为二(一块的大小与用户请求的大小相等,另一块的大小就是剩下的字节)。接下来,将分配给用户的那块内存传给用户,并将剩下的那块(如果有的话)返回到连接表上。调用free函数时,它将用户释放的内存块连接到空闲链上。到最后,空闲链会被切成很多的小内存片段,如果这时用户申请一个大的内存片段,那么空闲链上可能没有可以满足用户要求的片段了。于是,malloc函数请求延时,并开始在空闲链上翻箱倒柜地检查各内存片段,对它们进行整理,将相邻的小空闲块合并成较大的内存块。如果无法获得符合要求的内存块,malloc函数会返回NULL指针,因此在调用malloc动态申请内存块时,一定要进行返回值的判断。
Linux Libc6采用的机制是在free的时候试图整合相邻的碎片,使其合并成为一个较大的free空间。
 
 
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 养的小鸡总打架怎么办 小鸡一条腿瘸了怎么办 同窝小斗鸡打架怎么办 夏季羊长的慢怎么办 1岁吃母乳不吃饭怎么办 5个月宝宝黏妈妈怎么办 九个月宝宝不爱吃饭怎么办 20个月宝宝吐了怎么办 十个月的宝宝消化不好怎么办 两岁宝宝不爱喝水怎么办 两岁宝宝不爱喝水吃饭怎么办 两岁的宝宝不爱喝水怎么办 宝宝不爱吃饭不爱喝水怎么办 一多半宝宝爱喝水 不爱吃饭怎么办 1岁宝宝不爱吃饭喝水怎么办 两岁小宝宝不爱吃饭怎么办 4个月小宝宝咳嗽怎么办 3个月小宝宝咳嗽怎么办 2个月小宝宝咳嗽怎么办 8的岁儿童腿不直怎么办 作业盒子选错年级怎么办 两岁x型腿怎么办 绿萝叶子有水滴怎么办 打游戏变菜了怎么办 车被记号笔画了怎么办 水溶性彩铅受潮了怎么办 马克笔颜色涂深了怎么办 染发膏染眉毛了怎么办 用电容笔画画手有触感怎么办 CAD画图线性数字不居中怎么办 3d立体画笔堵塞怎么办 龋齿树脂填充老化后怎么办 小孩补过的牙疼怎么办 颜料弄到墙纸上怎么办 4岁的宝宝不爱涂色怎么办 oppo手机截图存不到相册怎么办 做的ih5保存不了怎么办 小偷偷东西发现后逃跑了怎么办? 网上有人传迷信诅咒怎么办 颜料粘在衣服上怎么办 家里有小偷撬锁怎么办