在正常申请内存时,所申请的内存大小都是固定的
比如说
int a = 0; //向内存申请四个字节的空间
char arr[10]; //向内存申请10个字节的空间
但在一下情况下,在程序开始运行之前是不知所需的空间的大小
此时有两种方案解决这个问题
1.开辟大量的空间,使得不论程序需要多大的空间,均能够满足。
2.动态内存管理
动态内存函数
动态内存函数申请的空间是位于堆区上的
与栈区上开辟的空间有些差异
栈区上开辟的空间是会被系统自动回收的,而堆区则不然
只有当程序运行结束后,堆区上开辟的空间方会被释放
这是便出现一个问题,程序如果7*24小时运行的,不释放已经不需要的空间
变化引起一些问题
如
void test()
{
int *p = (int *)malloc(100);
if(NULL != p)
{
*p = 20;
}
}
int main()
{
test();
while(1);
}
程序运行到while循环时,text中函数的空间以无作用,可也未释放。并且存储申请的空间地址的变量,随着函数运行的结束,已经销毁。无法得知所申请的这100个字节具体位置,程序继续运行下去,相当于内存永远的消失了100个字节,这也就是所谓的内存泄露
这也就是为什么存在释放空间函数的原因
开辟空间
malloc
函数声明
void* malloc (size_t size);
这个函数向内存申请一块连续可用的空间,并返回指向这块空间的指针。
- 如果开辟成功,则返回一个指向开辟好空间的指针。
- 如果开辟失败,则返回一个NULL指针,因此malloc的返回值一定要做检查。
- 返回值的类型是 void* ,所以malloc函数并不知道开辟空间的类型,具体在使用的时候使用者自己 来决定。
- 如果参数 size 为0,malloc的行为是标准是未定义的,取决于编译器。
calloc
函数声明
void* calloc (size_t num, size_t size);
函数的功能是为 num 个大小为 size 的元素开辟一块空间,并且把空间的每个字节初始化为0。
与函数 malloc 的区别只在于 calloc 会在返回地址之前把申请的空间的每个字节初始化为全0。
realloc
函数声明
void *realloc(void *ptr, size_t size)
重新分配ptr指向的空间,重新分配size个字节的空间。(前提:该空间是动态开辟的)
当 str == NULL时,与malloc相似。
开辟一块大小为size个字节的空间,返回其起始地址。
当 str 不为空时,存在两种情况
当str为起始,往后的空间大小足以开辟size个字节时,便在原有的空间后追加空间
当str往后的空间不足以开辟size个字节时,realloc会在内存中寻找一适宜的空间,将原空间中存储的数据拷贝如其中,并释放原有空间。
释放空间
free函数
void free (void* ptr);
将申请的空间的地址传入free函数即可
但要注意
- 如果参数 ptr 指向的空间不是动态开辟的,那free函数的行为是未定义的。
- 如果参数 ptr 是NULL指针,则函数什么事都不做。
动态内存函数注意事项
1.记得判断函数释放成功开辟空间,开辟失败会返回NULL。
可以在代码中添加一部分判断,如:
if (str == NULL)
{
perror("str:");
break;
}
2.在内存释放以后,不要再访问之前获得的地址
内存释放以后,该空间便被系统回收,再通过直接取到的地址访问,属于非负访问。
为了防止这个问题,可以在释放空间以后,将该指针置为空。