动态内存
1.动态内存分配
要点:
- 动态内存分配是在堆上开辟空间;
- 动态内存分配可以灵活地使用内存空间。
2.动态内存分配函数
2.1 malloc / calloc / realloc / free 总结
// Allocates memory blocks.
void* malloc (size_t size);// szie为要开辟空间的总大小
void* calloc (size_t num, size_t size);// num为元素类型的个数(Number of elements); size为该元素类型的大小
void* realloc (void* ptr, size_t size);// ptr为要重新开辟空间的其实地址; size为要重新开辟的大小
// Deallocates or frees a memory block.
void free (void* ptr);// ptr为所要释放空间的其实地址
知识要点:
-
malloc / calloc / realloc / free这些动态内存分配函数和释放动态内存空间函数都声明在stdlib.h中;
#include <stdlib.h> // 引入头文件
-
malloc / calloc / realloc内存分配函数,是在堆上开辟一块连续可用的空间;
-
malloc / calloc / realloc开辟成功则返回起始地址,开辟失败则返回NULL,所以要进行空指针判断,否则会发生空指针异常!;
-
函数的返回值为void*类型,这样可以让使用者根据自己的需求使用(强制类型转换);
-
malloc和realloc函数在开辟空间时,不会初始化空间,而calloc函数会将空间初始化为0;
-
realloc函数相当于内存扩容,而且在开辟好空间后会将原来的数据拷贝过来;
注意一个问题,realloc的第一个参数是一个指针,这个指针可以是任何指针吗?
展示,上例子:————realloc()函数需两个参数:一个是包含地址的指针(该地址由之前的malloc()、calloc()或realloc()函数返回),realloc()函数的第一个参数若为空指针,相当于分配第二个参数指定的新内存空间,此时等价于malloc()、calloc()或realloc()函数。另一个是要新分配的内存字节数。
翻译翻译:第一个参数,这个指针要么是空指针要么是开辟在堆上的指针。
-
free函数,注意它是释放 动态分配 的内存空间!,且它和动态内存分配函数时成对存在的。
7.1 释放动态空间
7.2 与动态内存分配函数成对出现,否则可能会发生内存泄漏!
free
2.2 一些试题,实践实践!
例1:
void funMem(char* p)
{
p = (char*)malloc(40);
}
void Test()
{
char* str = NULL;
funMem(str);
strcpy(str, "hello world");
printf("%s",str);
}
题解:
- 首先将指针变量str作为参数,用指针变量p来接收,这相当于在栈上开辟一块空间(p)来保存str的值(地址),也即str和p的指向是相同的(NULL),或者说是地址的临时拷贝。
- 虽然在函数funMem中将p的指向改为动态开辟的空间,但是str还是NULL; 而且p所指向的空间不知道是否开辟成功!
- 所以在字符串拷贝时会报错,向空指针拷贝,这不符合strcpy的使用规范。
请修改代码使其正常:
void funMem(char** p)
{
*p = (char*)malloc(40);
}
void Test()
{
char* str = NULL;
funMem(&str);
strcpy(str, "hello world");
printf("%s",str);
}
例2:
char* funM()
{
char p[] = "hello world";
return p;
}
void Test()
{
char* str = NULL;
str = funM();
printf("%s", str);
}
题解:
- 关键点在于funM函数中,将数组名p返回,也即返回数组的地址,但是数组是开辟在栈上的,属于临时变量,也就是函数就是栈帧销毁,则地址p为野指针!。
- 那么str也是野指针,那么打印的内容则为随机值!
请修改代码使其正常:
char* funM()
{
static char p[] = "hello world"; // 用static关键字修饰是的数组的生命周期延长!
return p;
}
void Test()
{
char* str = NULL;
str = funM();
printf("%s", str);
}
over!this is jimmy.