malloc,calloc,realloc小结

参考:百度百科以及

 
1、malloc
名称解释:malloc的全称是memory allocation,中文叫动态内存分配,当无法知道内存具体位置的时候,想要绑定真正的内存空间,就需要用到动态的分配内存。 
原型:extern void *malloc(unsigned int num_bytes);
 
头文件:在Visual C++6.0中用malloc.h或stdlib.h
 
功能:分配长度为num_bytes字节的内存块
返回值:如果分配成功则返回指向被分配内存的指针(此存储区中的初始值不确定),否则返回空指针NULL。
当内存不再使用时,应使用free()函数将内存块释放。函数返回的指针一定要适当对齐,使其可以用于任何数据对象。
说明:<1>.关于该函数的原型,在旧的版本中malloc返回的是char型指针,新的ANSIC标准规定,该函数返回为void型指针,因此必要时要进行类型转换。
^_^(写malloc的时候要强制类型转换,malloc前一定要加上(类型名*),否则无法通过编译,会报错,例如“不能将void*赋值给int*类型变量)
 < 2>.从函数声明上可以看出。malloc 和 new 至少有两个不同: new 返回指定类型的指针,并且可以自动计算所需要大小。 
 
2、realloc
 原型:extern void*realloc(void*mem_address,unsigned int newsize);
语法:指针名=(数据类型*)realloc(要改变内存大小的指针名,新的大小)//新的大小一定要大于原来的大小,不然的话会导致数据丢失!
 
头文件:#include<stblib.h>有些编译器需要#include<malloc.h>
功能: 先判断当前的指针是否有足够的连续空间,如果有,扩大mem_address指向的地址,并且将mem_address返回,如果空间不够,先按照newsize指定的大小分配空间将原有数据从头到尾拷贝到新分配的内存区域,而后释放原来mem_address所指内存区域,同时返回新分配的内存区域的首地址。即重新分配存储器块的地址。
^_^(可以这样理解:如果原来mem_address所指向的内存空间后面还有多余的空间,使得剩余空间+原有空间=newsize那么就不挪地方,直接在这里扩大地盘儿就ok了;可是如果剩余空间不够的话就从内存里再找一块连续的空间,大小为newsize,把原有数据都搬过去,并返回新的地址,ps:这是在内存的堆上进行的,realloc不仅能扩大还能缩小内存空间)
 
 特殊情况 :
如果mem_address为null,则realloc()和malloc()类似。分配一个newsize的内存块,返回一个指向该内存块的指针。 
如果newsize大小为0,那么释放mem_address指向的内存,并返回null。 
如果没有足够可用的内存用来完成重新分配(扩大原来的内存块或者分配新的内存块),则返回null.而原来的内存块保持不变。 
 
3、calloc
原型:void*calloc(unsigned n,unsigned size);
头文件:#include<stblib.h>或#include<stblib.h>
功能:在内存的动态存储区中分配n个长度为size的连续空间,函数返回一个指向分配起始地址的指针;如果分配不成功,返回NULL
跟malloc的区别:
calloc在动态分配完内存后,自动初始化该内存空间为零,而malloc不初始化,其内存空间是无意义的随机数据。
 


关于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原先所指向的内存地址丢失。

 

=========================================


函数定义:
void *realloc(void *ptr, size_t size);
上面的分析基本没有问题,但有两点要注意:
1.返回值可能与ptr的值不同,如果是不同的话,那么realloc函数完成后,ptr指向的旧内存已被free掉了。
2。如果返回NULL值,则分配不成功,而原来的ptr指向的内存还没有被free掉,要求程序显式free.

故p = (int *) realloc (p, sizeof(int) *15);语句有这么一个问题,
调用前p指向一个已分配成功的内存,而调用realloc时却失败(即返回NULL),此时,p原来指向的内存还没有free掉,而现在又找不到地址,这样就出现memory leak了。

关于这一点的确要注意,最好如下:
int *q
q = (int *) realloc (p, sizeof(int) *15);

if(!q) p =q;

posted @ 2013-05-10 12:03  Claire Liu  阅读(260)  评论(0编辑  收藏  举报