• 动态内存管理函数(malloc,calloc,realloc,free)


    动态内存函数

    1.1malloc和free

    C语言提供了一个动态内存开辟的函数:

    void* malloc (size_t size);

    这个函数向内存申请一块连续可用的空间,并返回指向这块空间的指针。

    • 如果开辟成功,则返回一个指向开辟好空间的指针。
    • 如果开辟失败,则返回一个NULL指针,因此malloc的返回值一定要做检查。
    • 返回值的类型是 void* ,所以malloc函数并不知道开辟空间的类型,具体在使用的时候使用者自己来决定。
    • 如果参数 size 为0,malloc的行为是标准是未定义的,取决于编译器

    使用malloc开辟空间实例: 

    1. #define _CRT_SECURE_NO_WARNINGS 1
    2. #include
    3. #include
    4. int main()
    5. {
    6. char* p = (char*)malloc(10);
    7. if (p == NULL)
    8. {
    9. perror("malloc");
    10. return 1;
    11. }
    12. int a = 97;
    13. for (int i = 0; i < 10; i++)
    14. {
    15. *p = a;
    16. printf("%c ",*p);
    17. a++;
    18. }
    19. free(p);
    20. p = NULL;
    21. return 0;
    22. }

    在上面的代码中我们看到了陌生的free函数,这个函数是做什么用的呢?

    可以看到标题写的malloc和free函数是搭配在一起来使用的,我们既然向内存借用申请了空间,那么在结束的是时候一定要free释放掉我们借来的“东西”。 

    C语言提供了另外一个函数free,专门是用来做动态内存的释放和回收的:

    void free (void* ptr);

    free函数用来释放动态开辟的内存。

    • 如果参数 ptr 指向的空间不是动态开辟的,那free函数的行为是未定义的。
    • 如果参数 ptr 是NULL指针,则函数什么事都不做。

    1.2calloc

    C语言还提供了一个函数叫 calloc , calloc 函数也用来动态内存分配:

    void* calloc (size_t num, size_t size);

    • calloc函数的功能是为 num 个大小为 size 的元素开辟一块空间,并且把空间的每个字节初始化为0。
    • calloc函数与函数 malloc 的区别只在于 calloc 会在返回地址之前把申请的空间的每个字节初始化为全0

    calloc函数实例:

    1. #define _CRT_SECURE_NO_WARNINGS 1
    2. #include
    3. #include
    4. int main()
    5. {
    6. int* p = (int*)calloc(10, sizeof(int));//开辟10个整型大小的空间----40字节
    7. if (p == NULL)
    8. {
    9. perror("calloc");
    10. return 1;
    11. }
    12. free(p);
    13. p = NULL;
    14. return 0;
    15. }

     

     开辟出来的40个字节的内存空间在最初就被初始化为0了

    1.3realloc

    realloc函数的出现让动态内存管理更加灵活。
    有时会我们发现过去申请的空间太小了,有时候我们又会觉得申请的空间过大了,那为了更合理使用内存,我们会对内存的大小做灵活的调整。那 realloc 函数就可以做到对动态开辟内存大小进行二次调整。
    
    void* realloc (void* ptr, size_t size);
    • ptr 是要调整的内存地址
    • size 是调整之后新大小
    • 返回值为调整之后的内存起始位置。
    • 这个函数在调整原内存空间大小的基础上,还会将原来内存中的数据移动到新的空间。

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

    • 情况1:原有空间之后有足够大的空间
    • 情况2:原有空间之后没有足够大的空间

    •  当是情况1 的时候,要扩展内存就直接原有内存之后直接追加空间,原来空间的数据不发生变化。
    • 当是情况 2 的时候,原有空间之后没有足够多的空间时,扩展的方法是:在堆空间上另找一个合适大小的连续空间来使用。这样函数返回的是一个新的内存地址
    1. #include
    2. int main()
    3. {
    4. int* ptr = (int*)malloc(100);
    5. if (ptr != NULL)
    6. {
    7. //业务处理
    8. }
    9. else
    10. {
    11. exit(EXIT_FAILURE);
    12. }
    13. //扩展容量
    14. //代码1
    15. ptr = (int*)realloc(ptr,INT_MAX);//这样可以吗?(如果申请失败会如何?)//更改申请的内存空间大小,如果更改的时候后续空间不足会发生原申请的内存空间指针丢失的后果
    16. //业务处理
    17. free(ptr);
    18. return 0;
    19. }

    正确使用方式应该是额外使用一个变量来接收  realloc  开辟的内存空间的地址,如果开辟成功则返回地址再赋给ptr,这样就保证了原来开辟空间的地址不会丢失,避免造成内存泄漏

     正确方式:

    1. #include
    2. int main()
    3. {
    4. int *ptr = (int*)malloc(100);
    5. if(ptr != NULL)
    6. {
    7. //业务处理
    8. }
    9. else
    10. {
    11. exit(EXIT_FAILURE);
    12. }
    13. //扩展容量
    14. //正确恰当的方式避免出现内存泄漏问题:
    15. int*p = NULL;
    16. p = realloc(ptr, 1000);
    17. if(p != NULL)
    18. {
    19. ptr = p;
    20. }
    21. //业务处理
    22. free(ptr);
    23. return 0;
    24. }

    感谢支持!

  • 相关阅读:
    C语言 柔性数组
    【Java基础】成员变量和局部变量及封装
    SpringMVC项目整合SSM统一结果封装
    推荐收藏!商汤智能座舱算法岗面试题7道(含解析)!
    英国Top20名校更偏爱IB申请党?
    5年经验之谈 —— 总结自动化测试与性能测试的区别!
    34基于MATLAB的杨氏双孔干涉条纹,可调节距离,孔的大小等参数,程序已调试通过,可直接运行。
    Mysql中json类型数据查询
    几何角度理解线性代数(3):点积与叉积
    文心一言 VS 讯飞星火 VS chatgpt (104)-- 算法导论10.1 2题
  • 原文地址:https://blog.csdn.net/AlanTZT/article/details/133655947