函数原型:void *malloc(unsigned int size);
功能:是在内存的动态存储区中分配一个长度为size的连续空间。此函数的返回值是分配区域的起始地址,或者说,此函数是一个指针型函数,返回的指针指向该分配域的开头位置。
如果分配成功则返回指向被分配内存的指针(此存储区中的初始值不确定,所有在malloc之后,一般是用memset()对该内存空间初始化,),否则返回空指针NULL。当内存不再使用时,应使用free()函数将内存块释放。函数返回的指针一定要适当对齐,使其可以用于任何数据对象。
新的ANSIC标准规定,该函数返回为void型指针,因此必要时要进行类型转换。它能向系统申请分配一个长度为num_bytes(或size)个字节的内存块。(c语言一般可以不用强转类型,但是c++需要,不然会报错)
示例:
char *p;
p = (char *)malloc( 100 );
if( NULL == p ){
/*报错malloc() error*/
return -1;
}
/*malloc()分配内存成功,则需要使用memset()初始化内存空间*/
/*memset( p, 0x00, sizeof( p ) ); 此处是错误演示,p为指针,sizeof(p)的大小不为100*/
memset(p,0x00, 100 ); /*100为malloc分配的内存空间大小*/
strcpy(p,"xxxxx"); /*内存空间的赋值操作*/
printf("%s",p); /*显示p所指向的内存空间的的值*/
/*动态分配的内存空间使用完后,需要进行释放*/
if( p != NULL ){
free(p);
p = NULL;
return 0;
}
函数原型:void* calloc(unsigned int num,unsigned int size);
功能:在内存的动态存储区中分配num个长度为size的连续空间,函数返回一个指向分配起始地址的指针;如果分配不成功,返回NULL。
注意:num:对象个数,size:一个对象占据的内存字节数。
相较于malloc函数,calloc函数会自动将内存初始化为0;
使用calloc()后,需要使用 free(起始地址的指针) 对内存进行释放,不然内存申请过多会影响计算机的性能,以至于得重启电脑。如果使用过后不free(),还可以使用该指针对该块内存进行访问。
calloc()的使用示例和malloc()基本一致,只是不需要memset初始化,同样需要free(),此处不在演示。
函数原型:extern void *realloc(void *mem_address, unsigned int newsize);
指针名=(数据类型*)realloc(要改变内存大小的指针名,新的大小)。
头文件:#include <stdlib.h> 有些编译器需要#include <malloc.h>
功能:先判断当前的指针后面是否有足够的连续空间,如果有,扩大mem_address指向的地址,并且将mem_address返回,如果空间不够,先按照newsize指定的大小分配空间,将原有数据从头到尾拷贝到新分配的内存区域,而后释放原来mem_address所指内存区域(注意:原来指针是自动释放,不需要使用free),同时返回新分配的内存区域的首地址,所以返回地址和mem_address可能不相同,后续应该操作返回的地址对应的内存,且将mem_address赋NULL,或者将返回地址重新赋给mem_address,然后使用mem_address操作
返回值:
- 返回的是一个void类型的指针:调用成功。(这就要求在你需要的时候进行强制类型转换)
- 返回NULL:当需要扩展的大小(第二个参数)为0,并且第一个参数不为NULL时。此时原内存变成“free(游离)”的了。
此处存在一个问题:
/*malloc(0)是合法的语句,会返还一个合法的指针,且该指针可以通过free去释放。
这就造成了很多人对realloc()的错误理解,认为当size为0时,实际上realloc()也会返回一个合法的指针,后面依然需要使用free去释放该内存(其实当size=0时,realloc()返回的是NULL)。比如:*/
void *new_ptr = realloc(ptr, size);
if (!new_ptr) {
free(ptr); /*当size=0时,realloc相当于free(ptr),此处在此free,则是double free了*/
return;
}
free(new_ptr);/*free(NULL)程序不做任何事,直接返回。但也是一个没必要的操作*/
return 0;
/*由于错误的认识,不去检验size是否为0,还是按照size不为0的逻辑处理,最后并free(new_ptr)或free(ptr)。这里就引入了double free的问题,造成程序崩溃。(实际调试的时候,如果size为0,那么返回的new_ptr为NULL)
所以,使用realloc前,最好检查ptr以及size的值。*/
- 返回NULL:当没有足够的空间可供扩展的时候。此时,原内存空间的大小维持不变。
当内存不再使用时,应使用free()函数将内存块释放。
注意事项:
- realloc失败的时候,返回NULL
- realloc失败的时候,原来的内存不改变,不会释放也不会移动
- realloc失败,返回值为NULL,涉及到一个问题:
char *p = NULL;
p = malloc(100);
if( NULL == p ){
/*报错malloc error*/
return -1;
}
strcpy( p, "xxxx" );
/*扩展p指向的内存空间的大小,增加20个字符*/
p = realloc(p,100+20);
if( NULL == p ){
/*问题出现:当realloc()函数执行失败,返回的值为NULL时,p此时就等于NULL,但是原来malloc函数分配的内存空间还存在,并且不能找到对应的地址的起始位置了,故无法free原来由malloc分配的内存空间*/
return -1;
}
/*扩展地址成功*/
strcpy(p+4,"yyyyyyyyyyyyyy");
printf("%s", p );
if( p != NULL ){
free(p);
p = NULL;
return 0;
}
上诉问题的解决方案:
/*声明一个临时指针变量*/
char *pTmp = NULL;
char *p = NULL;
p = malloc(100);
if( NULL == p ){
/*报错malloc error*/
return -1;
}
strcpy( p, "xxxx" );
/*malloc等操作不变,在接收realloc()函数返回值时使用pTmp*/
pTmp = realloc(p,100+20);
if( NULL == pTmp ){
/*扩展内存空间失败,释放原来malloc申请的空间*/
free(p);
return -1;
}
/*扩展内存空间成功*/
p = pTmp; /*将realloc()函数返回的地址赋值给p,浅拷贝,地址拷贝*/
pTmp = NULL; /*临时指针置空*/
strcpy(p+4, "yyyyyyyyy",);
printf( "%s", p );
if( p != NULL ){
free(p);
p = NULL;
return 0;
}
- 如果size为0,效果等同于free()。这里需要注意的是只对指针本身进行释放,例如对二维指针**a,对a调用realloc时只会释放一维,使用时谨防内存泄露。
- 传递给realloc的指针必须是先前通过malloc(), calloc(), 或realloc()分配的
- 传递给realloc的指针可以为空,等同于malloc。
有个问题未解决:realloc(p,100+20);进行内存空间的扩展,后续扩展的内存空间是否进行了初始化为0???