C语言动态内存管理如何深入理解才能成为专家?

2026-04-12 08:072阅读0评论SEO资源
  • 内容介绍
  • 文章标签
  • 相关推荐

本文共计2035个文字,预计阅读时间需要9分钟。

C语言动态内存管理如何深入理解才能成为专家?

目录

一、为什么会有动态内存

二、动态内存函数

1.malloc和free

2.calloc

3.realloc

三、动态内存函数常见错误

1.对NULL指针进行解引用操作

2.使用free释放一块动态分配内存的一部分

3.对静态内存进行操作

目录
  • 一、为什么会存在动态内存
  • 二、动态内存函数
    • 1.malloc和free
    • 2.calloc
    • 3.realloc
  • 三、动态内存函数常见错误
    • 2.对NULL指针进行解引用操作
    • 3.使用free释放一块动态开辟内存的一部分
    • 4.对静态内存进行free释放
    • 5.对同一内存空间多次释放
    • 6.动态开辟空间忘记释放
  • 四、经典笔试题
    • 1.笔试1
    • 2.笔试2
    • 3.笔试3
  • 总结

    一、为什么会存在动态内存

    int data=20;//在栈空间上开辟4个字节空间 char ch[5]={0};//在栈开辟5个字节连续空间

    上面展示的即为我们正常开辟固定的内存空间,它有两个方面的特点

    1.内存空间所占大小是固定的,不能改变的。

    2.创建数组时,必须指明长度大小,在编译时内存进行分配。

    很显然静态分配内存分配在一些场景,就暴露出它的弊端。如果在开发之前,我们不知道空间的需求,我们有时只有在程序运行的时候才能知道自己所需要空间大小,这时候我们只能使用动态分配内存了。

    二、动态内存函数

    1.malloc和free

    malloc函数的参数只有一个size_t size,向内存申请一块连续可用的空间,有几点需要注意

    1.如果开辟成功的话,返回指向开辟好空间的指针

    2.如果开辟失败的话,则返回NULL,因此每次开辟空间之后,都要进行检查

    3.malloc函数未定义返回类型,一切由使用者自己使用

    4.需引用stdlib.h头文件

    free函数是和malloc配套使用的,每次在堆开辟动态空间后,程序结束之前,必须进行空间释放,不然会出现动态空间泄露,在使用free时,仍需要注意几点

    1.如果指针指向的空间不是动态开辟的,不能用free进行释放

    2.如果指针指向的是null指针,则free函数什么事都不做

    3.free不能多次使用

    4.需引用stdlib.h头文件

    代码如下(示例):

    #include<stdio.h> #include<stdlib.h> #include<errno.h> #include<string.h> int main() { int* src = NULL; src = (int*)malloc(40);//开辟40字节动态内存 if (src == NULL) { printf("%s", strerror(errno)); return 1; } free(src);//进行动态内存释放 src = NULL; return 0; }

    相信有人会问,不是已经对动态内存进行释放,为什么还要令指针等于NULL,我们调试一把。

    这里我们可以发现,虽然动态内存进行free释放,但指针仍然指向被释放的动态内存的地址,如果不置空,就会造成野指针,非法访问的问题。

    2.calloc

    calloc和malloc最大的区别就是,malloc只负责对内存进行动态开辟,但calloc不仅开辟,还进行初始化。

    代码如下(示例):

    #include<stdio.h> #include<stdlib.h> #include<errno.h> #include<string.h> int main() { int* src = (int*)calloc(10, sizeof(int)); if (src == NULL) { printf("%s", strerror(errno)); return 1; } free(src);//进行动态内存释放 src = NULL; return 0; }

    我们调试一把可以发现,calloc在开辟空间时同时进行了初始化。所以如何我们对申请的内存空间的内容要求初始化,那么可以很方便的使用calloc函数来完成任务。

    3.realloc

    当我们一次开辟动态内存不够大的时候,realloc让动态内存更加的灵活。realloc几个参数:

    1.第一个参数为要调整内存的地址

    2.调整后大小

    3.调整后内存的起始位置

    C语言动态内存管理如何深入理解才能成为专家?

    为什么还要返回调整后内存的地址,不是直接就开辟好了吗?其实reallloc函数在开辟时有以下两种情况:

    1.原来的内存之后空间是足够的,则直接开辟

    2.原来的内存之后空间不够用。

    我们画图刨析一下

    情况1:直接追加空间,原来数据不变

    情况2:没有足够的空间,在堆上找一个大小合适的连续空间。所以函数返回的是一个新的内存地址。

    代码如下(示例)

    #include<stdio.h> #include<stdlib.h> #include<errno.h> #include<string.h> int main() { int* src = NULL; src = (int*)malloc(40);//开辟40字节动态内存 if (src == NULL) { printf("%s", strerror(errno)); return 1; } src = realloc(src, 80); if (src == NULL) { printf("%s", strerror(errno)); return 1; } free(src);//进行动态内存释放 src = NULL; return 0; }

    三、动态内存函数常见错误

    1.动态内存越界访问

    void test1() { int* src = (int*)malloc(20); if (NULL == src) { return 1; } int i = 0; for (i = 0; i < 6; i++) { (*src+i)=i } free(src); src = NULL; }

    在这里我们malloc只开辟了20个字节,但(*src+5)造成了越界访问

    2.对NULL指针进行解引用操作

    void test2() { int* src = (int*)malloc(INT_MAX);//此处INT_MAX为int的最大值 *src = 10;//如果src是NULL时,无法解引用 free(src); return 0; }

    这里未对开辟的动态内存空间进行是否为空的判断,当为空时,解引用就会出现错误。

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

    void test3() { int* src = (int*)malloc(40); int i=0; for(i=0;i<6;i++) { *(src+i)=i; src++; } free(src);//此时src不指向起始位置 }

    因为指针指向的地址发生变化,不在指向起始未知,进行free释放是非常危险的。

    4.对静态内存进行free释放

    void test4() { int a = 20; int* src = &a; free(src); }

    5.对同一内存空间多次释放

    void test5() { int* src = (int*)malloc(40); free(src); free(src);//多次释放 }

    第一个free已经将堆空间的动态内存进行释放,此时src已经是一个野指针,在进行释放是十分危险的。

    6.动态开辟空间忘记释放

    void test6() { int* src = (int*)malloc(40); if (src != NULL) { } while (1); }

    在开辟动态内存之后,一直进行while循环,为进行free释放,会造成内存泄漏。

    四、经典笔试题

    1.笔试1

    void test(char* src) { src = (char*)malloc(30); } int main() { char* src = NULL; test(src); strcpy(src, "wo yao jin da chang"); printf(src); free(src); }

    这里会输出wo yao jin da chang 吗?

    这里很明显,src仍然是NULL,所以无法输出wo yao jin da chang

    2.笔试2

    char* test() { char arr[] = "wo yao jin da chang"; return arr; } int main() { char* src = NULL; src = tset(); printf(src); return 0; }

    这里会输出wo yao jin da chang 吗?

    这里test函数确实把字符串地址传给了src,但是字符串是局部变量,当函数执行完之后,就销毁了,所以src输出的内容是随机的。

    3.笔试3

    void test() { char* src = (char*)malloc(50); if (src != NULL) { strcpy(src, "wo yao jin da chang"); } free(src); if (src != NULL) { strcpy(src, "taijuanlebujinle"); printf(src); } }

    这里会输出taijuanlebujinle 吗?

    这里对动态内存释放后,继续进行赋值,对野指针进行了访问是错误的。

    总结

    看到这里大家对动态内存管理已经有了一定的认识,应该特别注意这几点,在进行动态内存开辟之后进行判断是否为空,使用完后进行free释放,并且置空,防止动态内存泄露,只要记住这几点基本就可以很好的使用动态内存了。

    以上就是深入了解C语言的动态内存管理的详细内容,更多关于C语言动态内存管理的资料请关注自由互联其它相关文章!

    本文共计2035个文字,预计阅读时间需要9分钟。

    C语言动态内存管理如何深入理解才能成为专家?

    目录

    一、为什么会有动态内存

    二、动态内存函数

    1.malloc和free

    2.calloc

    3.realloc

    三、动态内存函数常见错误

    1.对NULL指针进行解引用操作

    2.使用free释放一块动态分配内存的一部分

    3.对静态内存进行操作

    目录
    • 一、为什么会存在动态内存
    • 二、动态内存函数
      • 1.malloc和free
      • 2.calloc
      • 3.realloc
    • 三、动态内存函数常见错误
      • 2.对NULL指针进行解引用操作
      • 3.使用free释放一块动态开辟内存的一部分
      • 4.对静态内存进行free释放
      • 5.对同一内存空间多次释放
      • 6.动态开辟空间忘记释放
    • 四、经典笔试题
      • 1.笔试1
      • 2.笔试2
      • 3.笔试3
    • 总结

      一、为什么会存在动态内存

      int data=20;//在栈空间上开辟4个字节空间 char ch[5]={0};//在栈开辟5个字节连续空间

      上面展示的即为我们正常开辟固定的内存空间,它有两个方面的特点

      1.内存空间所占大小是固定的,不能改变的。

      2.创建数组时,必须指明长度大小,在编译时内存进行分配。

      很显然静态分配内存分配在一些场景,就暴露出它的弊端。如果在开发之前,我们不知道空间的需求,我们有时只有在程序运行的时候才能知道自己所需要空间大小,这时候我们只能使用动态分配内存了。

      二、动态内存函数

      1.malloc和free

      malloc函数的参数只有一个size_t size,向内存申请一块连续可用的空间,有几点需要注意

      1.如果开辟成功的话,返回指向开辟好空间的指针

      2.如果开辟失败的话,则返回NULL,因此每次开辟空间之后,都要进行检查

      3.malloc函数未定义返回类型,一切由使用者自己使用

      4.需引用stdlib.h头文件

      free函数是和malloc配套使用的,每次在堆开辟动态空间后,程序结束之前,必须进行空间释放,不然会出现动态空间泄露,在使用free时,仍需要注意几点

      1.如果指针指向的空间不是动态开辟的,不能用free进行释放

      2.如果指针指向的是null指针,则free函数什么事都不做

      3.free不能多次使用

      4.需引用stdlib.h头文件

      代码如下(示例):

      #include<stdio.h> #include<stdlib.h> #include<errno.h> #include<string.h> int main() { int* src = NULL; src = (int*)malloc(40);//开辟40字节动态内存 if (src == NULL) { printf("%s", strerror(errno)); return 1; } free(src);//进行动态内存释放 src = NULL; return 0; }

      相信有人会问,不是已经对动态内存进行释放,为什么还要令指针等于NULL,我们调试一把。

      这里我们可以发现,虽然动态内存进行free释放,但指针仍然指向被释放的动态内存的地址,如果不置空,就会造成野指针,非法访问的问题。

      2.calloc

      calloc和malloc最大的区别就是,malloc只负责对内存进行动态开辟,但calloc不仅开辟,还进行初始化。

      代码如下(示例):

      #include<stdio.h> #include<stdlib.h> #include<errno.h> #include<string.h> int main() { int* src = (int*)calloc(10, sizeof(int)); if (src == NULL) { printf("%s", strerror(errno)); return 1; } free(src);//进行动态内存释放 src = NULL; return 0; }

      我们调试一把可以发现,calloc在开辟空间时同时进行了初始化。所以如何我们对申请的内存空间的内容要求初始化,那么可以很方便的使用calloc函数来完成任务。

      3.realloc

      当我们一次开辟动态内存不够大的时候,realloc让动态内存更加的灵活。realloc几个参数:

      1.第一个参数为要调整内存的地址

      2.调整后大小

      3.调整后内存的起始位置

      C语言动态内存管理如何深入理解才能成为专家?

      为什么还要返回调整后内存的地址,不是直接就开辟好了吗?其实reallloc函数在开辟时有以下两种情况:

      1.原来的内存之后空间是足够的,则直接开辟

      2.原来的内存之后空间不够用。

      我们画图刨析一下

      情况1:直接追加空间,原来数据不变

      情况2:没有足够的空间,在堆上找一个大小合适的连续空间。所以函数返回的是一个新的内存地址。

      代码如下(示例)

      #include<stdio.h> #include<stdlib.h> #include<errno.h> #include<string.h> int main() { int* src = NULL; src = (int*)malloc(40);//开辟40字节动态内存 if (src == NULL) { printf("%s", strerror(errno)); return 1; } src = realloc(src, 80); if (src == NULL) { printf("%s", strerror(errno)); return 1; } free(src);//进行动态内存释放 src = NULL; return 0; }

      三、动态内存函数常见错误

      1.动态内存越界访问

      void test1() { int* src = (int*)malloc(20); if (NULL == src) { return 1; } int i = 0; for (i = 0; i < 6; i++) { (*src+i)=i } free(src); src = NULL; }

      在这里我们malloc只开辟了20个字节,但(*src+5)造成了越界访问

      2.对NULL指针进行解引用操作

      void test2() { int* src = (int*)malloc(INT_MAX);//此处INT_MAX为int的最大值 *src = 10;//如果src是NULL时,无法解引用 free(src); return 0; }

      这里未对开辟的动态内存空间进行是否为空的判断,当为空时,解引用就会出现错误。

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

      void test3() { int* src = (int*)malloc(40); int i=0; for(i=0;i<6;i++) { *(src+i)=i; src++; } free(src);//此时src不指向起始位置 }

      因为指针指向的地址发生变化,不在指向起始未知,进行free释放是非常危险的。

      4.对静态内存进行free释放

      void test4() { int a = 20; int* src = &a; free(src); }

      5.对同一内存空间多次释放

      void test5() { int* src = (int*)malloc(40); free(src); free(src);//多次释放 }

      第一个free已经将堆空间的动态内存进行释放,此时src已经是一个野指针,在进行释放是十分危险的。

      6.动态开辟空间忘记释放

      void test6() { int* src = (int*)malloc(40); if (src != NULL) { } while (1); }

      在开辟动态内存之后,一直进行while循环,为进行free释放,会造成内存泄漏。

      四、经典笔试题

      1.笔试1

      void test(char* src) { src = (char*)malloc(30); } int main() { char* src = NULL; test(src); strcpy(src, "wo yao jin da chang"); printf(src); free(src); }

      这里会输出wo yao jin da chang 吗?

      这里很明显,src仍然是NULL,所以无法输出wo yao jin da chang

      2.笔试2

      char* test() { char arr[] = "wo yao jin da chang"; return arr; } int main() { char* src = NULL; src = tset(); printf(src); return 0; }

      这里会输出wo yao jin da chang 吗?

      这里test函数确实把字符串地址传给了src,但是字符串是局部变量,当函数执行完之后,就销毁了,所以src输出的内容是随机的。

      3.笔试3

      void test() { char* src = (char*)malloc(50); if (src != NULL) { strcpy(src, "wo yao jin da chang"); } free(src); if (src != NULL) { strcpy(src, "taijuanlebujinle"); printf(src); } }

      这里会输出taijuanlebujinle 吗?

      这里对动态内存释放后,继续进行赋值,对野指针进行了访问是错误的。

      总结

      看到这里大家对动态内存管理已经有了一定的认识,应该特别注意这几点,在进行动态内存开辟之后进行判断是否为空,使用完后进行free释放,并且置空,防止动态内存泄露,只要记住这几点基本就可以很好的使用动态内存了。

      以上就是深入了解C语言的动态内存管理的详细内容,更多关于C语言动态内存管理的资料请关注自由互联其它相关文章!