关于GetMemory
C语言关于动态内存的相关库函数
1.malloc
函数 void *malloc( unsigned int size)
;
在内存的动态存储区中分配一块长度为"size" 字节的连续区域。
如果分配成功,则返回所分配内存空间的首地址,否则返回NULL,申请的内存不会进行初始化。
“类型说明符”表示把该区域用于何种数据类型。(类型说明符*)表示把返回值强制转换为该类型指针。
例如:pc=(char *) malloc (100);
2.calloc
函数 void *calloc(unsigned int num, unsigned int size)
按照所给的数据个数和数据类型所占字节数,分配一个 num * size
连续的空间。
函数返回该存储区的起始地址。
calloc申请内存空间后,会自动初始化内存空间为 0,但是malloc不会进行初始化,其内存空间存储的是一些随机数据。
calloc函数与malloc 函数的区别仅在于一次可以分配n块区域。
例如: ps=(struct stu*) calloc(2,sizeof (struct stu))
; 其中的sizeof(struct stu)
是求stu
的结构长度。
3. realloc
函数:void *realloc(void *ptr, unsigned int size)
动态分配一个长度为size的内存空间,并把内存空间的首地址赋值给ptr,把ptr内存空间调整为size。
申请的内存空间不会进行初始化。
例如:p1=(float *)realloc(p1,16);
将原先开辟的8个字节调整为16个字节。
4.free
函数: void free(void *ptr)
作用:释放由上面3种函数所申请的内存空间。
C++语言关于动态内存的相关操作符
C++语言中用new和delete来动态申请和释放内存。
1.申请单个对象p = new int(value);
2.动态申请数组int *p = new int [100];
3.释放空间
int *p, *q;
p=new int;
q=new int[10];
delete p;
delete [ ]q;
new和malloc的区别
- new/delete是C++关键字,需要编译器支持。malloc/free是库函数,需要头文件支持。
- 使用new操作符申请内存分配时无须指定内存块的大小,编译器会根据类型信息自行计算。而malloc则需要显式地指出所需内存的尺寸。
- new操作符内存分配成功时,返回的是对象类型的指针,类型严格与对象匹配,无须进行类型转换,故new是符合类型安全性的操作符。而malloc内存分配成功则是返回void * ,需要通过强制类型转换将void*指针转换成我们需要的类型。
- new内存分配失败时,会抛出bac_alloc异常。malloc分配内存失败时返回NULL。
- new会先调用operator new函数,申请足够的内存(通常底层使用malloc实现)。然后调用类型的构造函数,初始化成员变量,最后返回自定义类型指针。delete先调用析构函数,然后调用operator delete函数释放内存(通常底层使用free实现)。
- C++允许重载new/delete操作符,特别的,布局new的就不需要为对象分配内存,而是指定了一个地址作为内存起始区域,new在这段内存上为对象调用构造函数完成初始化工作,并返回此地址。而malloc不允许重载。
- new操作符从自由存储区(free store)上为对象动态分配内存空间,而malloc函数从堆上动态分配内存。自由存储区是C++基于new操作符的一个抽象概念,凡是通过new操作符进行内存申请,该内存即为自由存储区。而堆是操作系统中的术语,是操作系统所维护的一块特殊内存,用于程序的内存动态分配,C语言使用malloc从堆上分配内存,使用free释放已分配的对应内存。自由存储区不等于堆,如上所述,布局new就可以不位于堆中。
下面看一道经典的面试题GetMemory
直接看代码
#include <iostream>
/************************************************************************/
/* 1、改变形参值,不会影响到实参,因此在Test1中GetMemory返回之后,str依然为NULL */
/* 2、strcpy不安全 */
/* 3、malloc没有free内存泄露 */
/************************************************************************/
void GetMemory1(char *p)
{
p = (char *)malloc(100);
}
void Test1(void)
{
char *str = NULL;
GetMemory1(str);
strcpy(str, "hello world"); //这里str为NULL
printf(str);
}
/************************************************************************/
/* 1、返回局部变量的指针,GetMemory返回时p已无效 */
/************************************************************************/
char *GetMemory2(void)
{
char p[] = "hello world";
return p;
}
void Test2(void)
{
char *str = NULL;
str = GetMemory2();
printf(str);
}
/************************************************************************/
/* 1、字面值存储在全局静态存储区,因此程序正常运行 */
/* 2、设计概念有问题,并没有分配内存,始终返回同一个地址 */
/* 3、c++11 会报错const char []”转换为“char * */
/* return const_cast<char *>("hello world"); */
/************************************************************************/
char *GetMemory3(void)
{
return "hello world";
}
void Test3(void)
{
char *str = NULL;
str = GetMemory3();
printf(str);
}
/************************************************************************/
/* 1、运行结果正确,形参传二级指针,实际是str的地址 */
/* 2、malloc之后需要判断是否成功 */
/* 2、strcpy不安全 */
/* 3、malloc没有free内存泄露 */
/************************************************************************/
void GetMemory4(char **p, int num)
{
*p = (char *)malloc(num);
}
void Test4(void)
{
char *str = NULL;
GetMemory4(&str, 100);
strcpy(str, "hello world");
printf(str);
}
/************************************************************************/
/* 1、运行结果正常打印world,但是操作是非法的 */
/* 2、malloc之后需要判断是否成功 */
/* 3、strcpy不安全 */
/************************************************************************/
void Test5(void)
{
char *str = (char *) malloc(100);
strcpy(str, "hello");
free(str);
//str = NULL 这里应将str置NULL
if(str != NULL)
{
strcpy(str, "world"); //这一步操作非法,free之后str指向的空间不再属于str
printf(str);
}
}
/************************************************************************/
/* 1、程序崩溃,str+6之后free,操作了非法地址空间 */
/* 2、malloc之后需要判断是否成功 */
/* 3、strcpy不安全 */
/************************************************************************/
void Test6()
{
char *str=(char *)malloc(100);
strcpy(str, "hello");
str+=6;
free(str);
if(str!=NULL)
{
strcpy(str, "world");
printf(str);
}
}
int main()
{
//Test1();
//Test2();
//Test3();
//Test4();
//Test5();
Test6();
}