malloc realloc calloc 的区别和联系 .

来源:互联网 发布:龙腾软件 编辑:程序博客网 时间:2024/05/01 21:23

ANSI C说明了三个用于存储空间动态分配的函数
(1) malloc 分配指定字节数的存储区。此存储区中的初始值不确定
(2) calloc 为指定长度的对象,分配能容纳其指定个数的存储空间。该空间中的每一位(bit)都初始化为0
(3) realloc 更改以前分配区的长度(增加或减少)。当增加长度时,可能需将以前分配区的内容移到另一个足够大的区域,而新增区域内的初始值则不确定

四个函数的声明分别是:

void* realloc(void* ptr, unsigned newsize);

void* malloc(unsigned size);

void* calloc(size_t nelem, size_t elsize);

free(q);                       //其中q为已经分配的块;

 malloc与calloc的区别为1块与n块的区别:malloc调用形式为(类型*)malloc(size):在内存的动态存储区中分配一块长度为"size"字节的连续区域,返回该区域的首地址。

 calloc调用形式为(类型*)calloc(n,size):在内存的动态存储区中分配n块长度为"size"字节的连续区域,返回首地址。

realloc 不能保证重新分配后的内存空间和原来的内存空间指在同一内存地址, 它返回的指针很可能指向一个新的地址。
所以,在代码中,必须把realloc返回的值,重新赋给 p 如:
p = (char *) realloc (p, old_size + new_size);
甚至,你可以传一个空指针(0)给 realloc ,则此时realloc 作用完全相当于malloc。
int* p = (char *) realloc (0,old_size + new_size); //全新分配一个内存空间,作用完全等同于以下这行: int* p = (char *) malloc(old_size + new_size);
calloc(len, size)与malloc相似,参数len为申请地址的单位元素长度,size为元素个数,如:
char* p;
p=(char*)calloc(sizeof(char),1000);

对realloc的详细语法说明:

void *realloc( void *memblock, size_t size );
一、如果memblock = 0, size != 0,表示为空指针分配空间,同malloc(memblock, size)
二、如果memblock != 0, size = 0,表示将已分配的空间释放,同free(memblock)
三、如果memblock != 0, size != 0,表示将已分配的空间重新分配,
1。如果size < memblock已分配内存大小,则将memblock的后部分切除,返回指针和memblock相等。
2。如果size > memblock已分配内存大小,
a)并且memblock大小和其后的自由内存总和大于等于size,则分配size大小的内存,返回指针和memblock相等。
b)如果memblock大小和其后的自由内存总和小于size,则在其他地方分配size大小的内存,返回指针和memblock不相等。如果其他地方也没有足够空间分配内存,则返回指针NULL。  

分配函数时再分配 realloc()   

使我们可以增、减以前分配区的长度(最常见的用法是增加该区)。
如果先分配一个可容纳长度为512的数组的空间,并在运行时填充它,但又发现空间不够,则可调用realloc扩充该存储空间。
如果在该存储区后有足够的空间可供扩充,则可在原存储区位置上向高地址方向扩充,并返回传送给它的同样的指针值。
如果在原存储区后没有足够的空间,则realloc分配另一个足够大的存储区,将现存的5 1 2个元素数组的内容复制到新分配的存储区。
因为这种存储区可能会移动位置,所以不应当使用任何指针指在该区中。
 注意,realloc的最后一个参数是存储区的newsize(新长度),不是新、旧长度之差。作为一个特例,若ptr是一个空指针,则realloc的功能与malloc相同,用于分配一个指定长度newsize的存储区。
这些分配例程通常通过sbrk(2)系统调用实现。该系统调用扩充(或缩小)进程的堆。虽然sbrk可以扩充或缩小一个进程的存储空间,但是大多数 malloc和free的实现都不减小进程的存储空间。释放的空间可供以后再分配,但将它们保持在malloc池中而不返回给内核。
应当注意的是,大多数实现所分配的存储空间比所要求的要稍大一些,额外的空间用来记录管理信息——分配块的长度,指向下一个分配块的指针等等。这就意味着如果写过一个已分配区的尾端,则会改写后一块的管理信息。这种类型的错误是灾难性的,但是因为这种错误不会很快就暴露出来,所以也就很难发现。
将指向分配块的指针向后移动也可能会改写本块的管理信息。其他可能产生的致命性的错误是:释放一个已经释放了的块;调用free时所用的指针不是三个 alloc函数的返回值等。因为存储器分配出错很难跟踪,所以某些系统提供了这些函数的另一种实现方法。每次调用这三个分配函数中的任意一个或free时都进行附加的出错检验。在调用连接编辑程序时指定一个专用库,则在程序中就可使用这种版本的函数。此外还有公共可用的资源(例如由4.3+BSD所提供的),在对其进行编译时使用一个特殊标志就会使附加的运行时间检查生效。
因为存储空间分配程序的操作对某些应用程序的运行时间性能非常重要,所以某些系统提供了附加能力。例如,SVR4提供了名为mallopt的函数,它使进程可以设置一些变量,并用它们来控制存储空间分配程序的操作。还可使用另一个名为mallinfo的函数,以对存储空间分配程序的操作进行统计。请查看所使用系统的malloc(3)手册页,弄清楚这些功能是否可用。
alloca函数
还有一个函数也值得一提,这就是alloca。其调用序列与malloc相同,但是它是在当前函数的栈帧上分配存储空间,而不是在堆中。其优点是:当函数返回时,自动释放它所使用的栈帧,所以不必再为释放空间而费心。其缺点是:某些系统在函数已被调用后不能增加栈帧长度,于是也就不能支持alloca 函数。尽管如此,很多软件包还是使用alloca函数,也有很多系统支持它。