【C语言】free()函数详解(动态内存释放函数)

news2025/4/16 13:55:53

🦄个人主页:修修修也

🎏所属专栏:C语言

⚙️操作环境:Visual Studio 2022


目录

 一.free()函数简介

1.函数功能

2.函数参数

void * ptr

3.函数返回值

4.函数头文件

二.free()函数的具体使用

1.使用free()函数完成malloc()开辟空间的释放

2.使用free()函数完成calloc()开辟空间的释放

3.使用free()函数完成realloc()开辟空间的释放

三.free()函数常见使用误区

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

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

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

4.动态开辟内存后忘记释放

结语


一.free()函数简介

我们先来看一下cplusplus.com - The C++ Resources Network网站上free()函数的基本信息:

1.函数功能

可以看到,free()函数的功能是:释放以前由malloc(),calloc(),realloc()函数动态开辟的内存空间.使其可以重新被分配.

2.函数参数

该函数有1个参数,是:

void free (void* ptr);

void * ptr

参数的类型无类型指针(void*),它指向先前由malloc(),calloc(),realloc()动态分配的内存块,它的作用是告诉函数要释放的内存块的起始位置.

3.函数返回值

函数的返回值类型空(void),它表示函数在运行结束后不需要返回值.

4.函数头文件

该函数包含在头文件<stdlib.h>中.

二.free()函数的具体使用

free()函数的使用场景是:当我们先前使用了malloc(),calloc(),realloc()函数开辟了动态内存空间,我们在不再使用这块空间时就应该及时使用free()函数将它释放掉,以免造成内存泄漏.

内存泄漏:如果动态开辟的内存没有被释放,那么这些内存就会一直占用系统资源,从而导致内存泄漏。内存泄漏会导致程序运行速度变慢,甚至崩溃。

1.使用free()函数完成malloc()开辟空间的释放

如下,我们使用free()函数将malloc()开辟空间的释放掉:

给free()函数传入:malloc()函数动态开辟的指针(即p).

int main()
{
    int* p = (int*)malloc(sizeof(int)*10);    //开辟10个整型大小空间
    if (p == NULL)       //如果开辟失败,则打印错误原因
    {
        //打印错误原因的一个方式
        printf("%s\n", strerror(errno));
    }
    else
    {
        int i = 0;
        for (i = 0; i < 10; i++)    //遍历赋值并打印这10个整型空间
        {
            *(p + i) = i;
            printf("%d ", *(p + i));
        }
        //可以正常使用p指针来操作这片空间了
    }

    free(p);    //释放p的内存空间
    p = NULL;         //将指针p置为NULL,防止其变成野指针

    return 0;
}

在vs编译器中运行查看结果:

虽然这里free()将malloc()动态开辟的内存释放后好像也没有发生什么变化,但如果我们因此不释放之前malloc()动态开辟的空间,那么这块空间就会一直占用着内存,既没有用,也没法让其他人使用.

还有一点需要注意的是,我们在free()完p指向的空间后,最好将p的内容置为NULL,否则这块空间已经被释放掉了,但你还保存着这块空间的地址,后续如果不小心再访问p的话,就会造成非法访问.


2.使用free()函数完成calloc()开辟空间的释放

如下,我们使用free()函数将calloc()开辟空间的释放掉:

给free()函数传入:calloc()动态开辟的内存指针(即p).

int main()
{
    int* p = (int*)calloc(10,sizeof(int));    //开辟10个整型大小空间
    if (p == NULL)       //如果开辟失败,则打印错误原因
    {
        //打印错误原因的一个方式
        printf("%s\n", strerror(errno));
    }
    else
    {
        int i = 0;
        for (i = 0; i < 10; i++)    //遍历并打印这10个整型空间
        {
            printf("%d ", *(p + i));//因为calloc()开辟的空间会自动初始化,所以我们可以不初始化这块空间,直接打印
        }
        //可以正常使用p指针来操作这片空间了
    }

    free(p);    //释放p的内存空间
    p = NULL;         //将指针p置为NULL,防止其变成野指针

    return 0;
}

在vs编译器中运行查看结果:

释放calloc()开辟的空间和malloc()一样,看不出来必要性,但却是非常有必要的.


3.使用free()函数完成realloc()开辟空间的释放

如下,我们使用free()函数将realloc()开辟空间的释放掉:

分别给free()函数传入:realloc()扩容后的内存块指针(即p).

int main()
{
    int* p = (int*)calloc(10,sizeof(int));    //开辟10个整型大小空间
    if (p == NULL)       //如果开辟失败,则打印错误原因
    {
        //打印错误原因的一个方式
        printf("%s\n", strerror(errno));
    }
    else
    {
        int i = 0;
        for (i = 0; i < 10; i++)    //遍历并打印这10个整型空间
        {
            printf("%d ", *(p + i));//因为calloc()开辟的空间会自动初始化,所以我们可以不初始化这块空间,直接打印
        }
        //可以正常使用p指针来操作这片空间了
    }
    printf("\n");
    p = (int*)realloc(p, 15 * sizeof(int));//将这块空间扩容到15个整型
    if (p == NULL)
    {
        printf("%s\n", strerror(errno));
    }
    else
    {
        int i = 0;
        for (i = 0; i < 15; i++)    //遍历并打印这15个整型空间
        {
            printf("%d ", *(p + i));
        }
    }

    free(p);    //释放p的内存空间
    p = NULL;         //将指针p置为NULL,防止其变成野指针

    return 0;
}

在vs编译器中运行查看结果:

realloc()扩容的内存块,扩容前的数据会保留,但新扩容的空间不会初始化,因此后面五个元素打印出的值是随机值.


三.free()函数常见使用误区

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

因为p是由编译器分配到栈区的,不属于堆区,因此不能使用free释放.

void test()
{
    int a = 10;
    int *p = &a;
    free(p);      //p不是动态开辟的,不能释放
}

 使用vs2022测试一下:

可以看到,该错误导致了程序出错.

而图中的报错"已执行断点指令"则是因为代码执行过程中出现了未定义的非法行为.


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

如下代码:

void test()
{
    int *p = (int *)malloc(100);
    p++;
    free(p);        //p不再指向动态内存的起始位置
}

 在vs2022中测试一下:

可以看到,该错误导致了程序异常终止.


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

如下代码:

void test()
{
    int *p = (int *)malloc(100);
    free(p);
    free(p);     //重复释放
}

 在vs2022中进行测试:

可以看到,该错误导致了程序出错.

这里列出了两个防止重复释放的小技巧:

  • 在设计时尽量遵从:谁开辟,谁回收的原则
  • 在free完后立刻将原动态开辟的指针置为NULL.

4.动态开辟内存后忘记释放

如下代码:

void test()
{
    int *p = (int *)malloc(100);
    if(NULL != p)
    {
        *p = 20;
    }
    //没有释放!
}

int main()
{
    test();
}

 如果动态开辟的内存忘记释放,程序不会报错,但会造成内存泄漏!

忘记释放不再使用的动态开辟的空间会造成内存泄漏.

内存泄漏:如果动态开辟的内存没有被释放,那么这些内存就会一直占用系统资源,从而导致内存泄漏。内存泄漏会导致程序运行速度变慢,甚至崩溃。

因此:

动态开辟的空间一定要释放,并且正确释放!

动态开辟的空间一定要释放,并且正确释放!

动态开辟的空间一定要释放,并且正确释放!


结语

希望这篇free()函数详解能对大家有所帮助,欢迎大佬们留言或私信与我交流.

有关更多动态开辟相关知识可以移步:

【C语言】内存的动态分配与释放icon-default.png?t=N7T8https://blog.csdn.net/weixin_72357342/article/details/134099965?spm=1001.2014.3001.5502

学海漫浩浩,我亦苦作舟!关注我,大家一起学习,一起进步!

相关文章推荐

【C语言】malloc()函数详解(动态内存开辟函数)

【C语言】realloc()函数详解(动态内存开辟函数)

【C语言】calloc()函数详解(动态内存开辟函数)

【C语言】free()函数详解(动态内存释放函数)

【C语言】memcpy()函数

【数据结构实战项目】C语言实现数据结构顺序表万字详解(附完整运行代码)

【实用编程技巧】不想改bug?初学者必须学会使用的报错函数assert!(断言函数详解)



C语言动态内存开辟相关库函数思维导图:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1147541.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

真实感渲染的非正式调研与近期热门研究分享

真实感渲染的非正式调研与近期热门研究分享 1 期刊1 Top2 Venues 2 Rendering Reserach1 Material2 BRDF3 Appearance Modeling4 Capture5 Light Transport光线传播6 Differetiable Rendring-可微渲染7 Ray Tracing8 Denoising降噪9 NeRF 3 VR/AR4 Non-Photorealistic Renderin…

Python学习——Day11--封装、继承、多态

一、封装 1.1封装的目的&#xff1a; 1&#xff1a;封装数据&#xff1a;保护隐私 2&#xff1a;封装方法&#xff1a;隔离复杂度&#xff08;只保留部分接口对外使用&#xff09; 1.2封装的方式 私有属性和方法: 私有成员变量&#xff1a;变量名以__开头&#xff08;2个下划线…

Spring Cloud之Nacos的学习【详细】

目录 Nacos的配置 Nacos的单机启动 服务注册 Nacos服务分级存储模型 优先访问同集群的服务 根据权重负载均衡 环境隔离Namespace Nacos调用流程 Nacos与Eureka注册对比 Nacos与Eureka的共同点 Nacos与Eureka的区别 Nacos配置管理 统一配置 配置自动刷新 多环境配…

2021美亚个人赛复现1

Individual_Container.zip.001下载以后显示是一个压缩包格式&#xff08;解压密码&#xff1a;MeiyaCup2021&#xff09; 解压得到Individual_Container加密容器&#xff0c;赛题存储在这里面 挂载密码HfsCk]<eUqc5Q{(DG$ugiGlt8ezGdaZ>!pQC-H\5BAc^gBo/^qq)/i21ufiNH&…

Windows 使用的一些小技巧

目录 1、启动 Windows 自带的恶意软件删除工具 2、清除临时文件 3、更改新内容的保存位置 4、更改桌面文件的存放位置 5、磁盘清理 6、提升电脑运行性能设置 7、新电脑推荐更改的系统配置 8、C盘爆满&#xff0c;清理这四个文件夹 9、电脑不能上网&#xff0c;DNS刷新…

【工具】FreePic2PDF+PdgCntEditor|PDF批量添加书签(Windows)

这俩软件都不大&#xff0c;比较便携。 FreePic2PDF&#xff1a; 我下载的来源&#xff1a;https://www.52pojie.cn/thread-1317140-1-1.html&#xff08;包含下载链接https://www.lanzoui.com/it4x6j4hbvc&#xff09;下载的结果&#xff1a;https://pan.baidu.com/s/1r8n5G42…

驱动day8作业

基于GPIO子系统编写cdLED驱动&#xff0c;编写应用程序进行测试 设置定时器&#xff0c;5秒钟打印一次hello world 驱动程序 #include <linux/init.h> #include <linux/module.h> #include<linux/of.h> #include<linux/of_gpio.h> #include<linu…

npm install报错,解决记录

第一步&#xff1a;检查和安装 我这里建议检查 1.node.js版本是否和前使用版本一致 2.npm版本是否和前使用版本一致 3.vue版本是否和前使用版本一致 4.vue脚手架是否和前使用版本一致 5.npm镜像是否和前使用版本一致 1.检查版本 【node版本】 命令&#xff1a;node -v 结果&a…

2023年下半年 系统集成项目管理工程师 真题考点(一二三四批次)(10月28、29)(网友回忆版)

文章目录 第一批部分考点整体管理采购管理风险管理二&#xff1a;EAC 第二批部分考点如下&#xff1a; 第三批部分考点如下&#xff1a; 第一批 部分考点 1、案例考了关键路径和工期&#xff0c;风险管理、采购、风险、招投标&#xff0c;整体管理。 2、计算题有关键路径和挣…

Windows下Jenkins自动化部署SpringBoot应用

Windows下Jenkins自动化部署SpringBoot应用 1、下载安装包 下载地址&#xff1a; 一个是 msi 程序&#xff1a; https://mirrors.aliyun.com/jenkins/windows/ 一个是 war 程序&#xff1a; https://get.jenkins.io/war-stable/ https://mirrors.jenkins.io/war/ 这里我…

关于线性模型的底层逻辑解读 (机器学习 细读01)

一 多元线性回归 线性回归是机器学习中 有监督机器学习 下的一种算法。 回归问题主要关注的是因变量(需要预测的值&#xff0c;可以是一个也可以是多个)和一个或多个数值型的自变量(预测变量)之间的关系。 需要预测的值:即目标变量&#xff0c;target&#xff0c;y&#xff0c…

稀疏矩阵存储

实验内容 1、&#xff08;1&#xff09;题目要求&#xff1a;如图所示&#xff0c;任意输入一个稀疏矩阵M&#xff0c;用三元组顺序表压缩存储该稀疏矩阵M&#xff0c;然后求其转置矩阵T&#xff0c;并输出转置矩阵T。 三元组的表示和初始化&#xff0c;用线性表 typedef st…

七彩童年有“米小圈”陪伴!

长期以来&#xff0c;我对孩子看的电视和动画片都很谨慎&#xff0c;怕有不好的内容会对孩子产生误导&#xff0c;不利于小孩子健康成长。令我没想到的是在这个假期里&#xff0c;“米小圈”的出现&#xff0c;让我对动画片的看法有了很大的改变&#xff0c;也让我对孩子观看动…

关爱通分享丨三大步九小步—重构管理价值链,驱动福利进阶

企业人才素质不断提升&#xff0c;对生活品质和精神层面的追求越来越高&#xff0c;也倒推企业不断改善管理、健全福利制度&#xff0c;激发员工的积极性和创造力。企业成本激增&#xff0c;但预期价值未能完全实现&#xff0c;为此&#xff0c;笔者在价值驱动管理理念的基础上…

如何使用贝锐花生壳内网穿透实现远程打印?

打印机是现在办公必不可少的工具&#xff0c;我们常常需要使用打印机复印或打印各种文件资料&#xff0c;下面给大家介绍下如何通过花生壳发布内网打印机实现外网远程打印。 PS&#xff1a;本文使用花生壳8客户端映射发布Toshiba e-STUDIO3540C打印机&#xff1b;其它打印机型…

【文献分享】基于线特征的激光雷达和相机外参自动标定

论文题目&#xff1a;Line-based Automatic Extrinsic Calibration of LiDAR and Camera 中文题目&#xff1a;基于线特征的激光雷达和相机外参自动标定 作者&#xff1a;Xinyu Zhang, Shifan Zhu, Shichun Guo, Jun Li, and Huaping Liu 作者机构&#xff1a;清华大学汽车安…

微信小程序备案教你快速小程序备案

下面是小程序备案的步骤&#xff1a; 1. 在微信公众平台上登录小程序账号&#xff0c;进入“设置”页面。 2. 点击“账号信息”栏&#xff0c;进入账号信息页面。 3. 点击“备案”栏&#xff0c;进入备案页面。 4. 在备案页面中&#xff0c;选择需要备案的域名或网站&#…

Flash(Animate)和木疙瘩的元件学习和理解

元件就是讲一个图形或素材封装到一个容器里面&#xff01;可以被任何舞台、页面通过从仓库中拖拽的方式无限重复使用&#xff0c;类似unity中的预制体&#xff01; Flash(Animate)和木疙瘩中元件唯一区别&#xff1a;木疙瘩中一个元件A中不可以添加另一个元件B&#xff01; 一…

操作系统运行机制

文章目录 操作系统运行机制特权指令VS非特权指令内核态VS用户态中断和异常内中断(异常)外中断中断机制基本原理中断处理过程 系统调用系统调用和库函数的区别为什系统调用时必须的&#xff1f;什么功能需要用到系统调用系统调用的过程小结 操作系统内核 操作系统运行机制 特权…

防火墙的技术(NAT NAT-Server 策略路由 ) 第二十课

防火墙的技术(NAT NAT-Server 策略路由 ) 第二十课 环境的准备工作 1 配置如图所示的所有的IP地址 1 配置IIP地址 2 配置防火墙中的基本配置 防火墙的默认管理口的ip地址 <USG6000-ISP-LOCAL>display current-configuration 2023-10-28 02:54:08.620 !Software Ver…