目录
一.malloc和free
1.1 malloc
malloc的函数原型为:
void* malloc(size_t size);
这个函数向内存的堆区申请一块指定大小的连续可用空间,并返回指向这块空间的指针。
a.如果开辟成功,则返回一个指向开辟好空间的指针。
b.如果开辟失败,则返回一个空指针,因此malloc的返回值一定要做检查。
c.函数的返回值是void *,所以malloc函数并不知道开辟空间的类型,具体使用时自己指定。
d.如果size是0的话,malloc的行为是C语言标准未定义的,取决于编译器。
1.2 free
free是用来释放动态内存空间的,函数原型为:
void* free(void* ptr);
a.如果参数ptr指向的空间不是动态开辟的,那free函数的行为是会报错的。
b.如果参数ptr是一个空指针,则释放无效。
注意:
1.函数malloc和free所需要的对应的头文件是#include<stdlib.h>。
2.动态内存函数申请的空间是堆区的,而普通变量申请的空间是在栈区。
3.每次申请动态空间后要判断是否开辟成功,否则后果自负。
4.最后一定要将申请的动态空间释放。
5.释放后的指针并不是空的,而是申请前的值,所以我们最后要把他放空。
#include<stdio.h>
#include<stdlib.h>
int main()
{
float* ptr=(*float)malloc(sizeof(float));//开辟一个浮点型的空间
if(ptr==NULL)//一定要判断是否开辟成功
perror("malloc");//用来显示错误
......
free(ptr);//最后释放掉动态空间
ptr=NULL;
return 0;
}
二.calloc和realloc
2.1 calloc
calloc函数也是用来分配内存空间的,函数原型为:
void* calloc(size_t num,size_t size);
a.num是元素个数,size是元素类型所占的字节数。
b. 与malloc不同的是calloc在返回指针前,会把空间初始化为0.
比如:
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<stdlib.h>
int main()
{
int* p = (int*)calloc(10,sizeof(int));
if (p == NULL)
{
perror("malloc fail!");
return 1;
}
int i = 10;
while (i--)
{
printf("%d ", *p++);
}
free(p);
p=NULL;
return 0;
}
这里的结果是10个0,但是如果用malloc那么结果就是10个随机数。
2.2 realloc
realloc函数是用来调整动态空间的大小的,可以调大,也可以调小,其函数原型为:
void* realloc(void* ptr,size_t size);
prt指向要调整的内存空间,size是调整后的新空间大小。
调整空间有两种情况:
a.原有空间之后有足够大的空间
如图,ptr所指的空间有后又足够的空间,那么调大的空间就会直接追加在原来的空间,函数返回的空间地址跟原地址相同,原来的数据不会发生变化。
b.原有空间之后没有足够大的空间
当新的空间太大时,原来地址的空间不能容下,realloc函数就会返回一个新的地址,重新开辟一个新的空间,并且自动把原来的数据拷贝到新的空间,然后再自动释放掉原来的空间。
注意:
1.realloc函数的指针形参是指向堆区动态空间的指针,并不是栈区的普通指针。
2.时候用realloc时,由于情况不确定,所以通常用一个新的临时指针来接受realloc的返回值。
使用临时指针的原因:如果使用原指针,若是realloc开辟空间失败,那么会返回一个空指针,造成原指针不再指向原空间,也就找不到到来的数据,造成内存泄漏。
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<stdlib.h>
int main()
{
int* p = (int*)calloc(10,sizeof(int));
if (p == NULL)
{
perror("malloc fail!");
return 1;
}
int* ptr;//临时指针
ptr = (int*)realloc(p, 20* sizeof(int));//使用临时指针接收调整后的空间
if (ptr== NULL)
{
perror("realloc fail!");
return 1;
}
p = ptr;//将新的空间传回来
free(ptr);
free(p);
ptr = NULL;
p = NULL;
return 0;
}
三.常见的动态内存的错误
3.1 对空指针的解引用操作
int main()
{
int *p=(int*)malloc(4);
*p=20;//没有判断,p可能是空指针
return 0;
}
3.2 对动态内存空间的越界访问
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<stdlib.h>
int main()
{
int* p = (int*)malloc(40);
for (int i = 0; i <= 10; i++)
{
*(p + i) = i;//访问第10个元素的时候的时候,为越界
}
free(p);
p = NULL;
return 0;
}
3.3 对非动态内存空间使用free
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<stdlib.h>
int main()
{
int a = 6;
int* p = &a;//p不是指向动态空间的指针
free(p);
return 0;
}
3.4 使用free释放动态空间的一部分
#include<stdio.h>
#include<stdlib.h>
int main()
{
int* p = (int*)malloc(20);
p = p + 2;
free(p);
return 0;
}
free函数释放必须是从空间的起始地址开始释放,不可释放部分。
3.5 对同一块空间多次释放
int main()
{
int* p = (int*)malloc(20);
......
free(p);
free(p);
return 0;
}
3.6 对动态空间忘记释放
注意:
malloc//realloc//calloc开辟的内存空间,除非手动free释放或者程序结束,否则被不会释放,将会造成内存泄漏。