了解动态内存管理函数melloc、calloc、free、realloc,实现内存管理*!

动态内存管理

笔记自取链接:动态内存管理笔记


文章目录


导言

众所周知~,内存的分配如下图所示:

了解动态内存管理函数melloc、calloc、free、realloc,实现内存管理*!

我们已经不满足于

int a = 0;
int b[3] = 0;

这种变量占有固定的字节数,修改不了

我们比较熟悉的是静态区和栈区的变量类型,那么堆区里面有什么?

接下来让我们一起了解一下动态内存分配类型的函数


一、mallco 开辟动态内存空间

需包含头文件:stdlib.h

返回值和参数

void* malloc (size_t size);

解读:在堆区上申请size大小的空间,返回堆区上这个空间的起始地址

如何使用:

int* p = (int *)malloc(4);//我们专门申请一块空间放整型

如果直接解引用

int* p = (int *)malloc(4);
*p = 1;//有风险

malloc开辟失败会返回一个空指针

我们需要判断是否申请内存成功

if(p == NULL)
{
    return -1;//分配失败
}
else
{
    *p = 3;//使用该空间   
}

二、free 释放动态内存空间

需包含头文件:stdlib.h

我们用完mellco函数申请的空间时,这块空间不想要

用free函数释放空间


free函数的返回值和参数

void free (void* ptr);

解读:给free函数传一个指针(必须是动态空间的起始地址),指针所指向的空间释放掉,如果传NULL,什么都不执行


!!!!!!!!!!!!!!!但是!!!!!!!!!!!!!!!!

我们运行的时候 p的地址如下

了解动态内存管理函数melloc、calloc、free、realloc,实现内存管理*!

了解动态内存管理函数melloc、calloc、free、realloc,实现内存管理*!


当我们释放内存空间时

了解动态内存管理函数melloc、calloc、free、realloc,实现内存管理*!

了解动态内存管理函数melloc、calloc、free、realloc,实现内存管理*!

虽然空间释放掉了,p指针所指向的地址还是刚才的地方,p仍然可以访问,这样子就很危险,因为p现在是一个野指针

free(p);
p = NULL;

把它变成空指针,这样就安全了


三、calloc 初始化+开辟动态内存空间

需包含头文件:stdlib.h

返回值和参数

void* calloc (size_t num, size_t size);

解读:在堆区上申请num个size大小的空间返回堆区上这个空间的起始地址,并且把所有元素初始化成0

如何使用

int* p = (int*)calloc(10, 4);//40字节

其他功能和melloc类似

  • 开辟失败返回NULL,成功返回空间的起始地址
  • 使用的时候判断是否失败
  • 使用结束的时候需要用free释放该内存空间

唯一区别就是melloc不会初始化


四、realloc 调整动态内存空间大小

一段时间后,我们可能会觉得,之前申请的空间太小或者过大了,为了合理且灵活使用内存时,我们可以用realloc对动态内存空间进行大小的修改

返回值和参数

void* realloc (void* ptr, size_t size);

解读:

  • ptr 是要调整的内存地址

  • size是调整之后新大小

  • 返回值为调整之后的内存起始位置

  • 这个函数调整原内存空间大小的基础上,还**可能会将原来内存中的数据移动到新的空间**

    realloc在调整内存空间两种情况:

    1. 原有空间之后有足够大的空间:直接原有内存之后直接追加空间,原来空间的数据不发生变化

    了解动态内存管理函数melloc、calloc、free、realloc,实现内存管理*!

    1. 原有空间之后没有足够多的空间:在堆空间上新找一个大小合适的连续空间来存放,realloc函数返回的是一个新的内存地址

    了解动态内存管理函数melloc、calloc、free、realloc,实现内存管理*!

但在使用过程中需要注意

int* p = (int*)malloc(10);
//我想要20个字节
int* p = (int*)realloc(p, 20);
//这样子写真的可以吗

如果遇到调整动态空间错误,realloc会返回空指针,这样我们原本的空间也丢失了

我们需要一个临时变量接受指针

int* ptr = (int*)realloc(p, 20);

if(ptr != NULL)
{
    p = ptr;//调整成功
}
else
{
    return -1;
}

free(p);
p = NULL;

小结

虽然动态内存空间使用很灵活,但我们还是需要注意以下常见的错误

  • 对NULL(空)指针的解引用操作

    注意,在申请内存空间时,可能失败,导致返回空指针

  • 对动态开辟空间的越界访问

    使用该空间时候,所申请超出空间的范围

  • 对非动态开辟内存使用free释放

    free只能释放动态内存!!!

  • 使用free释放一块动态开辟内存的一部分

    传递给free去释放的指针必须是所开辟动态空间的起始地址

    开辟动态空间的起始地址不能随便++或–等操作改变地址

    除非创建临时参数使用

  • 对同一块动态内存多次释放

    free(p);
    free(p);
    

    错误,不能连续释放


    正确写法:

    free(p);
    p = NULL;
    free(p);
    p = NULL;
    
  • 动态开辟内存忘记释放(内存泄漏)

    内存释放两种方式:

    • free函数释放
    • 程序运行结束自动释放

    如果一个程序(比如服务器)一直运行,而你不释放这块内存,内存空间就一直被占用,浪费


上一篇:roarctf_2019_realloc_magic


下一篇:C语言动态内存分配malloc、calloc、realloc