c语言-常见的动态内存错误

文章目录

  • 前言
  • 一、常见的动态内存错误
    • 1.1 对空指针进行解引用操作
    • 1.2 对动态开辟的空间进行越界访问
    • 1.3 对非动态开辟的空间使用free()
    • 1.4 使用free()释放一块动态开辟的空间时,释放不完全
    • 1.5 对同一块动态开辟的空间进行多次释放
    • 1.6 动态开辟的空间使用后,不进行释放操作
  • 二、经典笔试题
    • 2.1 题目一
    • 2.2 题目二
  • 总结


前言

本篇文章叙述使用c语言提供的库函数实现动态内存管理的过程中,出现常见的错误。


一、常见的动态内存错误

1.1 对空指针进行解引用操作

#include<stdio.h>
#include<stdlib.h>
#include<limits.h>
int main()
{int* p = (int*)malloc(INT_MAX);*p = 20;  //当申请空间失败时,p = NULLfree(p);p = NULL;return 0;
}

以上代码容易出现问题,当使用malloc()申请空间时,申请失败会返回空指针,那么此时p为一个空指针,对一个空指针进行解引用,造成错误。
正确的做法:在使用动态申请的空间之前,首先进行判断是否申请成功。

改正后

#include<stdio.h>
#include<stdlib.h>
#include<limits.h>
#include<string.h>
#include<errno.h>
int main()
{int* p = (int*)malloc(INT_MAX);//判断if(NULL == p){printf("%s\n", strerror(errno));return 1; //结束函数}//使用*p = 20;  //释放操作free(p);p = NULL;return 0;
}

1.2 对动态开辟的空间进行越界访问

int main()
{//申请10个整型大小的空间int* p = (int*)malloc(10*sizeof(int));if (NULL == p){printf("%s\n", strerror(errno));return 1;}//为申请的空间赋值int i = 0;for (i = 0; i <= 10; i++){*(p + i) = i;}//释放free(p);p = NULL;return 0;
}

以上代码通过malloc()申请10个int大小的空间后,对这块空间访问时,*(p+10)造成越界访问

1.3 对非动态开辟的空间使用free()

int main()
{int arr[10] = { 0 };free(arr);return 0;
}

以上代码将arr指向的空间进行了释放操作,造成了错误。arr指向的空间属于栈区的空间,不属于动态开辟的空间,不可以进行释放操作。

1.4 使用free()释放一块动态开辟的空间时,释放不完全

int main()
{//申请一块10个int大小的空间int* p = (int*)malloc(10 * sizeof(int));if (NULL == p){printf("%s\n", strerror(errno));return 1;}//使用*p = 10;p++;  //p往前走4个字节,p的指向改变导致释放空间时发生错误//释放free(p);p = NULL;return 0;
}

以上代码使用动态申请的空间后,改变了p的指向,导致释放内存时,释放不完全。

1.5 对同一块动态开辟的空间进行多次释放

int main()
{//申请一块10个int大小的空间int* p = (int*)malloc(10 * sizeof(int));if (NULL == p){printf("%s\n", strerror(errno));return 1;}//使用*p = 10;//释放free(p);  //1free(p);  //2p = NULL;return 0;
}

以上代码将动态申请的空间进行了两次释放操作,导致出现错误
第一次释放p指向的空间后,p依然指向这块内存,但已经不属于当前程序的空间。
第二次释放操作时,p指向的空间不属于当前程序,造成非法访问。

1.6 动态开辟的空间使用后,不进行释放操作

int* getMomery()
{//申请一块10个int大小的空间int* p = (int*)malloc(10 * sizeof(int));if (NULL == p){printf("%s\n", strerror(errno));return NULL;}return p;
}int main()
{int* p = getMomery();*p = 10;return 0;
}

以上代码造成内存泄露,属于重量级错误。
使用getMemory()申请一块空间并将起始位置返回后,在main()使用这块空间,结束后没有进行释放操作,导致内存泄露。


二、经典笔试题

2.1 题目一

#include<stdio.h>
#include<stdlib.h>
//笔试题讲解
void getMemory(char* p)
{p = (char*)malloc(100);
}void test(void)
{char* str = NULL;getMemory(str);strcpy(str, "hello world");printf(str);
}
int main()
{test();return 0;
}

问:以上代码运行会输出什么内容?
答:以上代码不仅不会输出内容,还会造成内存泄露和因将字符串复制到NULL中,造成错误。
首先,str为局部变量,类型为char*; p为形式参数,类型为char*,p的改变不会改变str
当getMemory()调用结束后,p被销毁,但是申请的内存没有进行释放,造成内存泄露。
strcpy(NULL,“hello worldl”)会造成对空指针进行解引用,造成错误。

修改代码

void getMemory(char** p)
{*p = (char*)malloc(100);
}void test(void)
{char* str = NULL;getMemory(&str);if(str != NULL){strcpy(str, "hello world");printf(str);}//释放空间free(str);str = NULL;
}int main()
{test();return 0;
}

输出结果
在这里插入图片描述


2.2 题目二

//2. 返回局部变量的地址或临时变量的地址
char* getMemory(void)
{char p[] = "hello world";return p;
}
void test(void)
{char* str = NULL;str = getMemory();printf(str);
}
int main()
{test();return  0;
}

问:test()执行时打印什么?
答:打印随机内容
原因:p数组开辟的空间在栈区,当getMemory()执行结束时数组的空间被操作系统回收,那么str接收数组首元素地址时,str属于野指针,操作野指针指向的空间属于非法访问内存,因为访问的空间不属于当前程序。


总结

本篇文章介绍了利用c语言的提供的库函数实现动态内存管理时易出现的问题,并介绍了几道经典的关于内存管理的笔试题。

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

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

相关文章

Android14源码剖析:MediaPlayer与MediaPlayerService区别?(五十四)

简介: CSDN博客专家,专注Android/Linux系统,分享多mic语音方案、音视频、编解码等技术,与大家一起成长! 优质专栏:Audio工程师进阶系列【原创干货持续更新中……】🚀 优质专栏:多媒体系统工程师系列【原创干货持续更新中……】🚀 人生格言: 人生从来没有捷径,只…

MySQL数据库 | 事务中的一些问题(重点)

文章目录 什么是事务&#xff1f;事务的几个特性(ACID) -重点原子性(Atomicity)一致性(Consistency)隔离性(Isolation)持久性(Durability) Mysql中事务操作隐式事务显式事务 savepoint关键字只读事务事务中的一些问题&#xff08;重点&#xff09;隔离级别脏读解决办法 幻读解决…

美易官方《惊爆财务丑闻,有空头已经赚了十倍》

惊爆财务丑闻&#xff0c;“四大粮商”之首ADM股价暴跌&#xff0c;有空头已经赚了十倍 近日&#xff0c;一起惊爆市场的财务丑闻让全球投资者为之震惊。作为全球最大的农业综合企业之一&#xff0c;“四大粮商”之首的ADM&#xff08;Archer Daniels Midland&#xff09;被曝涉…

信息检索与数据挖掘 | (八)语言建模的IR

文章目录 &#x1f4da;语言生成模型&#x1f4da;平滑&#x1f407;线性插值平滑方法(Lelinek-Mercer)&#x1f407;dirichlet 平滑&#x1f407;Vector space&#xff08;向量空间&#xff09; vs BM25 vs LM &#x1f4da;语言生成模型 传统的语言生成模型可以用于识别或生成…

【Pytorch】搭建一个简单的泰坦尼克号预测模型

介绍 本文使用PyTorch构建一个简单而有效的泰坦尼克号生存预测模型。通过这个项目&#xff0c;你会学到如何使用PyTorch框架创建神经网络、进行数据预处理和训练模型。我们将探讨如何处理泰坦尼克号数据集&#xff0c;设计并训练一个神经网络&#xff0c;以预测乘客是否在灾难…

MySQL数据库查询语句之组函数,子查询语句

组函数 以组为操作单位&#xff0c;一组数据得到一个结果。 在没有手动分组的前提下&#xff0c;整张表默认为一组数据 max(列名)&#xff1a;获取最大值 min(列名)&#xff1a;获取最小值 sum(列名)&#xff1a;获取总和 avg(列名)&#xff1a;获取平均值 count(列名)&a…

20.云原生之GitLab CICD实战

云原生专栏大纲 文章目录 GitLab RunnerGitLab Runner 介绍Gitlab Runner工作流程 Gitlab集成Gitlab RunnerGitLab Runner 版本选择Gitlab Runner部署docker-compose方式安装kubesphere中可视化方式安装helm方式安装 配置gitlab-runner配置gitlab-ci.ymlgitlab-ci.yml 介绍编写…

基于FPGA的高效乘法器

1、设计思路 二进制的乘法运算与十进制的乘法运算相似&#xff0c;如下图所示&#xff0c;二进制数据6’b110010乘以二进制数据4’b1011&#xff0c;得到乘积结果10’b1000100110。 图1 二进制乘法运算 仔细观察上图发现&#xff0c;乘数最低位为1&#xff08;上图紫色数据位&a…

机器学习:什么是监督学习和无监督学习

目录 一、监督学习 &#xff08;一&#xff09;回归 &#xff08;二&#xff09;分类 二、无监督学习 聚类 一、监督学习 介绍&#xff1a;监督学习是指学习输入到输出&#xff08;x->y&#xff09;映射的机器学习算法&#xff0c;监督即理解为&#xff1a;已知正确答案…

期末考试发等级发成绩,就用易查分!

期末考试后&#xff0c;学校老师如何发布私密成绩&#xff1f;易查分可以轻松创建等级、成绩查询系统&#xff0c;让家长仅看到自己孩子成绩。 支持查询后留言反馈&#xff0c;电子签名确认签收等高级功能&#xff0c;节省老师沟通时间&#xff0c;大大提升工作效率。 &#x1…

linux安装docker(入门一)

环境&#xff1a;centos 7(linux) 网站 官网: https://docs.docker.com/ Docker Hub 网站: https://hub.docker.com/ 容器官方概述 一句话概括容器&#xff1a;容器就是将软件打包成标准化单元&#xff0c;以用于开发、交付和部署。 容器镜像是轻量的、可执行的独立软件包 &…

【百面机器学习】读书笔记(一)

本文系列主要作用就是读书笔记&#xff0c;自己看的话比较杂&#xff0c;没怎么归类过&#xff0c;所以现在跟着这个分类走一遍。本文主要内容为前两章&#xff0c;特征工程和模型评估。 如果我想起一些相关的内容也会做适当的补充&#xff0c;主打就是一个intuition&#xff…

OpenCV书签 #直方图算法的原理与相似图片搜索实验

1. 介绍 直方图算法&#xff08;Image Histogram Algorithm&#xff09; 通过统计图像中各个颜色值的分布情况来提供关于图像颜色特征的信息&#xff0c;它可以用来衡量两张图片在颜色分布上的相似度&#xff0c;进而可以用来进行图像相似度的比较&#xff0c;因此&#xff0c…

电脑录屏软件大比拼,哪个最适合你?

现如今&#xff0c;电脑录屏软件成为了许多用户记录、分享和教学的重要工具。从游戏玩家到专业制作人员&#xff0c;都需要高效的录屏软件。本文将介绍三款优秀的电脑录屏软件&#xff0c;通过详细的步骤和简洁的介绍&#xff0c;帮助用户轻松掌握这些工具的使用方法。 电脑录屏…

附1:k8s服务器初始化

转载说明&#xff1a;如果您喜欢这篇文章并打算转载它&#xff0c;请私信作者取得授权。感谢您喜爱本文&#xff0c;请文明转载&#xff0c;谢谢。 关联文章&#xff1a; 《RKE快速搭建离线k8s集群并用rancher管理界面》 1.创建普通用户sre并赋予sudo权限 # adduser sre # ec…

【动态规划】879. 盈利计划

作者推荐 【动态规划】【广度优先搜索】【状态压缩】847 访问所有节点的最短路径 本文涉及知识点 动态规划汇总 LeetCode879. 盈利计划 集团里有 n 名员工&#xff0c;他们可以完成各种各样的工作创造利润。 第 i 种工作会产生 profit[i] 的利润&#xff0c;它要求 group[…

大模型独立解答30道国际奥数难题,能力接近金牌选手!

谷歌旗下的AI研究机构DeepMind和纽约大学的研究人员联合开发了一个AI模型——AlphaGeometry。 AlphaGeometr是一种神经符号模型,内置了大语言模型和符号推理引擎等功能,主要用于解决各种超难几何数学题&#xff0c;同时可以自动生成易于查看的解题原理。 为了验证AlphaGeomet…

React Router v6 改变页面Title

先说正事再闲聊 1、在路由表加个title字段 2、在index包裹路由 3、在App设置title 闲聊&#xff1a; 看到小黄波浪线了没 就是说默认不支持title字段了 出来的提示&#xff0c; 所以我本来是像下面这样搞的&#xff0c;就是感觉有点难维护&#xff0c;就还是用上面的方法了 …

Linux配置yum源以及基本yum指令

文章目录 一、yum介绍二、什么是软件包三、配置yum源四、一键配置yum源【三步走】五、yum指令搜索软件安装软件卸载软件 六、其他yum指令更新内核更新软件更新指定软件显示所有可更新的软件清单卸载指定包并自动移除依赖包删除软件包&#xff0c;以及软件包数据和配置文件 一、…

快速上手MyBatis Plus:简化CRUD操作,提高开发效率!

MyBatisPlus 1&#xff0c;MyBatisPlus入门案例与简介1.1 入门案例步骤1:创建数据库及表步骤2:创建SpringBoot工程步骤3:勾选配置使用技术步骤4:pom.xml补全依赖步骤5:添加MP的相关配置信息步骤6:根据数据库表创建实体类步骤7:创建Dao接口步骤8:编写引导类步骤9:编写测试类 1.2…