动态内存开辟(malloc,calloc,free,realloc)

前言:本篇文章介绍了如何正确利用malloc、calloc、realloc函数的动态开辟我们要使用的内存,还有在进行动态内存开辟的时候常见的一些错误

为什么会存在内存开辟?

首先,我们回忆一下到目前为止我们掌握的的内存开辟方式有哪些:


    int a = 0;//在栈区连续开辟4个字节的空间
    int arr[10] = { 0 };//在栈区连续开辟40个字节的空间

上述的内存开辟方式有两个特点:

  • 内存开辟的大小是固定的
  • 数组在声明时必须指定数组的长度,它开辟的内存在编译时候进行分配

malloc、free、calloc、realloc函数介绍

malloc

函数原型


    void *malloc( size_t size );

函数功能

这个函数向内存申请一块连续可用,大小为size个字节的空间。如果开辟成功,则返回开辟好空间的起始地址;如果开辟失败,则返回一个NULL指针,因此要对malloc函数的返回值一定要做检查。如果参数size为0,malloc的行为是标准是未定义的,取决于编译器。

函数使用


    int *p = NULL;
    p = (int *)malloc(10);//开辟一个大小为10个字节的空间
    //对malloc的返回值进行检查
    if (p == NULL)
    {
        perror("use malloc");
        exit(EXIT_FAILURE);
    }
    //...
    //使用这块空间

free

函数原型


    void free( void *memblock );

函数功能

C语言提供了一个函数free,专门用来释放和回收的起始地址为memblock动态开辟的内存块。如果参数memblock指向的空间不是动态开辟的,那free函数的行为是未定义的;如果参数memblock是NULL指针,则函数什么事都不做。

函数使用


    int *p = NULL;
    p = (int *)malloc(10 * sizeof(int));//开辟一个大小为10个整型的空间
    //对malloc的返回值进行检查
    if (p == NULL)
    {
        perror("use malloc");
        exit(EXIT_FAILURE);
    }
    //...
    //使用这块空间
    free(p);//使用完这块空间一定要记得释放,否则会形成内存泄露
    p = NULL;//这里很有必要

注意:malloc实际开辟的空间比我们开辟的空间要大,因为需要有一些空间来记录开辟空间的大小方便使用free函数。所以我们在用malloc开辟空间时尽量大一些,太小感觉没有必要。

calloc

函数原型


    void *calloc( size_t num, size_t size );

函数功能

函数的功能是开辟num个大小为size的空间,并且把空间的每个字节初始化为0。如果开辟成功,则返回开辟好空间的起始地址;如果开辟失败,则返回一个NULL指针。这个函数与malloc的区别只在calloc会在返回地址之前把申请的空间的每个字节初始化为0。

函数使用


    int *p = NULL;
    p = (int *)malloc(10 * sizeof(int));//开辟一个大小为10个整型的空间
    //p所指向的那块空间全部初始化为0
    //对malloc的返回值进行检查
    if (p == NULL)
    {
        perror("use malloc");
    exit(EXIT_FAILURE);
    }
    //...
    //使用这块空间
    free(p);//使用完这块空间一定要记得释放,否则会形成内存泄露
    p = NULL;

realloc

函数原型


    void *realloc( void *memblock, size_t size );
参数介绍
  • memblock:要调整那块空间的起始地址
  • size: 调整后空间的大小
返回值介绍
  • 情况一:原来的那块空间后边有足够的空间来进行调整,realloc函数直接在原来的空间后边追加空间,原来空间的数据依然存储在原来的空间,返回值也依然是原来空间的起始地址
  • 情况二:原来的那块空间后边没有足够的空间来进行调整,realloc函数会重新找一块空间,将原来空间的值放进去,然后自动释放原来的空间,返回值为新开辟空间的起始地址

注意:由于以上两种情况,在使用realloc函数调整大小的时候一定要对realloc函数的返回值进行检查,然后在将返回值赋值给维护动态内存开辟那个指针,否则如果realloc函数没有调整成功,则原来的那块空间的起始地址也找不到了,会出现内存泄露的问题

函数功能

有时我们发现以前申请的空间不够用或者是太大了,为了合理的使用内存,我们一定要对开辟好的内存大小进行灵活的调整。realloc函数就可以做到对已经动态开辟好的内存大小进行调整,realloc函数的出现让动态内存管理变得更加灵活。

函数使用


    int *p = NULL;
    p = (int *)malloc(100);//堆空间上开辟一个大小为100个字节的空间
    if (p == NULL)
    {
        perror("use malloc");
        exit(EXIT_FAILURE);
    }
    //扩展容量
    int *ptr = NULL;
    ptr = realloc(p, 200);//调整动态开辟内存大小为200个字节
    if (ptr == NULL)
    {
        perror("use malloc");
        exit(EXIT_FAILURE);
    }
    else
    {
        p = ptr;
        //参数检查无误后,将新地址赋值给维护动态开辟内存的指针
    }
    free(p);//使用完之后释放空间
    p = NULL;

动态内存开辟常见错误

  • 动态开辟内存后不进行释放,造成内存泄漏
  • 对动态开辟的内存进行多次释放
  • 对动态开辟的内存进行部分释放,不能对维护动态内存开辟的指针进行处理
  • 释放并非动态开辟的内存是非法的
  • 对动态开辟的内存进行越界访问
  • 对空指针进行解引用操作
  • 对已经释放的内存进行二次访问

猜你喜欢

转载自blog.csdn.net/hansionz/article/details/80883991