在这里说的都是在堆区进行的空间开辟和释放
一、malloc函数
malloc函数向内存申请一块连续可用的空间,并返回指向这块空间的指针
如果开辟成功,则返回一个指向开辟好空间的指针。但不会初始化开辟空间的内容 如果开辟失败.则返回一个NULL指针,因此malloc函数的返回值一定要做检查。 返回值的类型void*,所以malloc函数并不知道开辟空间的类型,所以要根据需求自己来决定 如果参数size为0,malloc的行为是标准是未定义的,取决于编译器。
malloc申清的内存空间,当程序退出时,会还给操作系统 但是当程序不退出,动态申请的内存,不会主动释放, 需要使用free函数来释放。
free函数
如果参数Ptr指向的空间不是动态开辟的,那free函数的行为是未定义的。
int a = 1;
int* p = &a;
free(p);
比如这里就是错的用法 如果参数ptr是NULL指针则函数什么事都不做·
养成一个好习惯 在把空间释放后,把刚才开辟空间得到的起始指针赋为空指针,避免之后再次去使用它指向的一片已经归还给操作系统的空间
free函数底层原理是 在我们开辟动态内存空间时,一般情况下编译器会在你传的地址前多开辟4个字节来存放你记录的开辟的字节,再用free函数释放时实际上是从你传的地址的前四个字节开始释放,利用之前存在这的数据精准释放
注意 用free函数一次要释放就释放完,不能只释放一部分
还有不要对同一块内存空间进行多次释放
还有不要忘记用free函数进行开辟的动态内存的释放 ,比如说在函数内声明p创建指针变量来存放开辟空间的起始指针,当函数运行完退出去后,p被销毁相当于丢失了你开辟空间的首地址,相当于找不到这块空间,导致释放不了这个空间,并且也不能使用这块空间造成内存泄漏。动态申请的空间不会因为出了作用域就销毁(还给操作系统),只有两种方式销毁 第一 free函数 第二 程序结束(退出)
calloc函数
函数的功能是为num个大小为size的元素开辟一块空间,并目把空间的每个字节初始化为0。 与函数malloc的区别只在于calloc会在返回地址之前把申请的空间的每个字节初始化为全0。
int main()
{
int* p = calloc(10, sizeof(int));
if (p==NULL)
{
perror("calloc");
return 1;
}
int i = 0;
for (i = 0; i < 10; i++)
printf("%d ", p[i]);
free(p);
p = NULL;
return 0;
}
这里的结果是
就是因为calloc函数在开辟空间时会把空间的每一个字节都初始化为0
当释放完内存后,p就没用了,把p赋为空指针
当你申请的空间过大也有可能申请失败。
realloc函数
realloc函数的出现让动态内存管理更加灵活。 有时会我们发现过去申请的空间太小了,有时候我们又会觉得申请的空间过大了,那为了合理的时候内存, 我们要对内存的大小做调整。 realloc 函数就可以起到作用
ptr是之前申请空间的起始地址,size表示的是新一次要申请的空间,但是如果ptr为空指针,realloc函数相当于调用了malloc函数
realloc函数有两种对空间的扩充方式
当原来开辟的空间的后面有足够的空间来满足你的扩容需求,那么编译器将在原来的基础上扩容,返回的地址也就是原来开辟空间的首地址
当原来开辟的空间的后面没有足够的空间来满足你的扩容需求,那么realloc函数将会进行一下四步
第一 开辟新的空间
第二 将旧空间的数据拷贝到新空间
第三 释放旧的空间
第四 返回新空间的地址
当然如果是减少空间,返回的就是刚才开辟的那个空间的起始地址,减少空间减少的部分归还操作系统
注意 当realloc函数在哪都无法将空间扩容时将会返回空指针
所以说
int main()
{
int* p = calloc(10, sizeof(int));
if (p==NULL)
{
perror("calloc");
return 1;
}
int i = 0;
for (i = 0; i < 10; i++)
printf("%d ", p[i]);
p = (int*)realloc(p, 4000);
for (i = 0; i < 1000; i++)
printf("%d ", p[i]);
free(p);
p = NULL;
return 0;
}
这种写法是不合理的,这里不适合把realloc函数的返回值直接赋给p指针,因为当realloc函数在哪都无法将空间扩容时将会返回空指针,导致之前申请的空间的起始地址没有了,以至于我们找不到刚才申请开辟的空间,并且也无法释放刚才开辟的空间,造成内存泄漏也就是既用不到那片内存空间,我也找不到了。
int main()
{
int* p = calloc(10, sizeof(int));
if (p==NULL)
{
perror("calloc");
return 1;
}
int i = 0;
for (i = 0; i < 10; i++)
printf("%d ", p[i]);
int* str = (int*)realloc(p, 4000000000);
if (str != NULL)
p = str;
for (i = 0; i < 1000; i++)
printf("%d ", p[i]);
free(p);
p = NULL;
return 0;
}
应该判断不为空指针后再赋给p