来源于《高质量C/C++编程》的几道经典面试题

news2025/1/12 3:58:47

本文介绍几个非常经典的笔试题,原题+详细解析,供参考

  • 题目1:非法访问+内存泄漏
  • 题目2:返回栈空间地址问题--非法访问
  • 题目3:内存泄漏
  • 题目4:非法访问

题目1:非法访问+内存泄漏

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;
}

请问运行Test 函数会有什么样的结果?
结果:在这里插入图片描述
解析:

void Getmemory(char* p)//用p来接收str的数据,p是形参,形参是实参的一份临时拷贝
{
	p = (char*)malloc(100);//给p开辟一个100字节的空间。
	//还有这里开辟了空间后,并没有释放,造成内存泄漏。
}
void test(void)
{
	char* str = NULL;
	Getmemory(str);//将str这个指针传过去,相当于传值过去,并不是传址输入,对形参的改变并不会影响实参。
	strcpy(str, "hello world");//这里的str还是空指针,并没有空间给它拷贝,形成NULL非法访问,这里就出错了。
	printf(str);
}
int main()
{
	test();
	return 0;
}

1.str传给p的时候,p是str的临时拷贝,有自己的独立空间,当GetMemory函数内部申请了空间后,地址放在p中,str仍然是NULL。当Getmemory函数返回之后,strcpy拷贝的时候,形成了非法访问。
2.在Getmemory函数内部,动态申请空间,但是没有释放,造成内存泄漏

正确做法1:

void Getmemory(char** p)//str是一级指针,&str就是二级指针
{
	*p = (char*)malloc(100);//*p就相当于str,就是给str开辟一个100字节的空间
}
void test(void)
{
	char* str = NULL;
	Getmemory(&str);//这里进行传址输入,利用形参修改实参
	strcpy(str, "hello world");//这里的str就拥有了100字节的空间了
	printf(str);
	free(str);//释放空间
	str=NULL//手动置NULL
}
int main()
{
	test();
	return 0;
}

正确做法2:

char* Getmemory(char* p)//那Getmemory函数返回值就要改成char *类型接收指针
{
	p = (char*)malloc(100);
	return p;//将p返回
}
void test(void)
{
	char* str = NULL;
	str=Getmemory(str);//这里用指针str来接收Getmemory函数内部形参开辟的空间
	strcpy(str, "hello world");
	printf(str);
	free(str);//释放空间
	str=NULL//手动置NULL
}
int main()
{
	test();
	return 0;
}

在这里插入图片描述

题目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 函数会有什么样的结果?
结果:
在这里插入图片描述
解析:

char* Getmemory(void)
{
	char p[] = "hello world";//创建一个数组p,里面存放着字符串
	return p;//返回数组名,也就是返回了数组首元素的地址
}
void test(void)
{
	char* str = NULL;
	str = Getmemory();//Getmemory函数的返回值用str来接收
	//数组p的首元素地址用str来接收
	//但要注意的是,p数组是在Getmemory内部创建,创建在栈区,出了函数,这个空间就要返回给操作系统,不再受指针p操控。
	//所以str虽然得到了数组的首元素地址,但这片空间已经不再属于数组空间了,所以形成了非法访问
	printf(str);//打印str指向的字符
}
int main()
{
	test();
	return 0;
}

这个问题统称为返回栈空间地址问题
就是在栈上开辟的空间,并将指向这块空间的地址返回,但这块空间的使用者发现改变,不再是原先的使用者了,而再根据地址找到这块空间来访问就会出问题。
这个要按自己的实际需求来正确修改。

题目3:内存泄漏

void Getmemory(char** p, int num)
{
	*p = (char*)malloc(num);
}

void test(void)
{
	char* str = NULL;
	Getmemory(&str, 100);
	strcpy(str, "xiao tao");
	printf(str);
}
int main()
{
	test();
	return 0;
}

请问运行Test 函数会有什么样的结果?
在这里插入图片描述
解析:
这个题目跟第一题的修改后的题目差不多

void Getmemory(char** p, int num)
{
	*p = (char*)malloc(num);//开辟100个字节空间给*p  *p就是str
	//所以给str开辟了100字节的空间
}

void test(void)
{
	char* str = NULL;
	Getmemory(&str, 100);//传址输入,可以通过对形参修改而修改实参
	strcpy(str, "xiao tao");//对str指向的空间进行拷贝
	printf(str);//打印拷贝后的空间内容
	//最最重要的一点是,空间申请后,释放呢?这里没有释放所以最后会造成内存泄漏
	free(str);//释放内存
	str = NULL;
}
int main()
{
	test();
	return 0;
}

题目4:非法访问

void test(void)
{
	char* str = (char*)malloc(100);
	strcpy(str, "xiao tao");
	free(str);
	if (str != NULL)
	{
		strcpy(str, "666");
		printf(str);
	}
}
int main()
{
	test();
	return 0;
}

请问运行Test 函数会有什么样的结果?
在这里插入图片描述
解析:

void test(void)
{
	char* str = (char*)malloc(100);//开辟100个字节的空间
	strcpy(str, "xiao tao");//给指向srt的空间进行拷贝
	free(str);//释放空间
	//free的功能是将原先指向这块空间的指针与这块空间之间的联系断开,这块空间不再首这个指针调控,回归到操作系统,供有需要的使用
	//而free释放空间后并不会将原先指向这块空间的指针置为空指针,还是指向原先的地方,所以下面的操作就进行下去了
	//所以这个指针又去访问那块空间让其被覆盖成666,这就造成非法访问了
	if (str != NULL)//如果str不为空指针进行下面操作
	{
		strcpy(str, "666");
		printf(str);//打印指向str那块空间的内容
	}
}
int main()
{
	test();
	return 0;
}

正确做法:在不改变原意的基础上修改:

void test(void)
{
	char* str = (char*)malloc(100);//开辟100个字节的空间
	strcpy(str, "xiao tao");//给指向srt的空间进行拷贝
	free(str);//释放空间
	str = NULL;//释放空间后手动置为NULL,让下面的操作无法进行
	if (str != NULL)//如果str不为空指针进行下面操作
	{
		strcpy(str, "666");
		printf(str);//打印指向str那块空间的内容
	}
}
int main()
{
	test();
	return 0;
}

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

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

相关文章

Apache Doris 系列: 基础篇-使用BitMap函数精准去重(2)

1. 背景 Apache Doris 原有的BitMap函数虽然比较通用, 但在亿级别的BitMap大基数并交计算性能较差,主要是由以下两个原因造成的: 当BitMap的基数过大,大小超过1GB时,网络或者磁盘的处理时间较长BE节点扫描完数据后传…

机器自动翻译古文拼音 - 十大宋词 - 念奴娇 赤壁怀古 苏轼

念奴娇 赤壁怀古 苏轼 大江东去,浪淘尽,千古风流人物。故垒西边,人道是,三国周郎赤壁。乱石穿空,惊涛拍岸,卷起千堆雪。江山如画,一时多少豪杰。 遥想公瑾当年,小乔初嫁了&#xf…

机器自动翻译古文拼音 - 十大宋词 - 扬州慢 淮左名都 姜夔

扬州慢淮左名都 南宋姜夔 淮左名都,竹西佳处,解鞍少驻初程。 过春风十里,尽荠麦青青。 自胡马窥江去后,废池乔木,犹厌言兵。 将黄昏,清角吹寒,都在空城。 杜郎俊赏,算而今重到须惊…

springmvc 整合 thymeleaf 模板引擎

springmvc 整合 thymeleaf 模板引擎 第一步&#xff1a;导入 web.xml 文件 -> <?xml version"1.0" encoding"UTF-8"?> <web-app xmlns"http://xmlns.jcp.org/xml/ns/javaee"xmlns:xsi"http://www.w3.org/2001/XMLSchema-ins…

代码随想录算法训练营第31天 二叉树 java :39. 组合总和 40.组合总和II 131.分割回文串

文章目录LeetCode 39. 组合总和本题题解思路LeetCode 40.组合总和II本题题解思路LeetCode 131.分割回文串本题题解思路那么在代码里什么是切割线呢&#xff1f;那么在代码里什么是切割线呢&#xff1f;总结LeetCode 39. 组合总和 本题题解 思路 根据递归三部曲来分析 递归函…

网站如何进行整站优化?

如果要做优化或者选择性优化&#xff0c;一定要区分关键词优化和全站优化&#xff0c;米贸搜整理如下&#xff0c;希望可以帮助到你&#xff1a;一、全站优化的概念:1.一般认为&#xff0c;全站点优化是指通过SEO技术&#xff0c;使其网站成为搜索引擎中的权威站点。当达到效果…

面试汇总-多线程

目录 1、Thread.sleep(0)的作用 2、Synchronized 2.1、特性 2.2、说一说自己对于 synchronized 关键字的了解&#xff1a; 2.3、synchronized关键字的底层原理(JVM如何实现重量级锁) 2.4、Jdk1.6之后对synchronized做的优化 2.4.1、锁粗化 2.4.2、锁消除 2.5、线程池的…

Scala运算符

算术运算符 关系运算符 Java 和 Scala 中关于“”的区别 逻辑运算符 赋值运算符 位运算符 Scala运算符总结 算术运算符 基本与Java一致 对于除号“/”&#xff0c;它的整数除和小数除是有区别的&#xff1a;整数之间做除法时&#xff0c;只保留整 数部分而舍弃小数部分…

JDBC学习笔记(黑马)

目录 一、JDBC快速入门 二、JDBC API详解 &#xff08;一&#xff09;DriverManager &#xff08;二&#xff09;Connection &#xff08;三&#xff09;Statement &#xff08;四&#xff09;ResultSet &#xff08;五&#xff09;PreparedStatement 三、数据库连接池…

前端实现水印的两种方式(DOM和Canvas)

&#x1f431; 个人主页&#xff1a;不叫猫先生 &#x1f64b;‍♂️ 作者简介&#xff1a;前端领域新星创作者、阿里云专家博主&#xff0c;专注于前端各领域技术&#xff0c;共同学习共同进步&#xff0c;一起加油呀&#xff01; &#x1f4ab;系列专栏&#xff1a;vue3从入门…

Python 海象运算符

✅作者简介&#xff1a;人工智能专业本科在读&#xff0c;喜欢计算机与编程&#xff0c;写博客记录自己的学习历程。 &#x1f34e;个人网站&#xff1a;小嗷犬的技术小站 &#x1f34a;个人信条&#xff1a;为天地立心&#xff0c;为生民立命&#xff0c;为往圣继绝学&#xf…

图纸版本混乱?BOM表管理困难?看SolidWorks PLM如何高效助力产品数据管理

“随着集团的日益壮大&#xff0c;我们越来越重视信息化系统的建设工作&#xff0c;但在研发生产的过程中我们经常会遇到图纸版本混乱、数据查找不便的问题&#xff1b;特别是在产品设计好后&#xff0c;还需要花费很多时间手动整理BOM表&#xff0c;整理期间由于数据量太大&am…

2023年,对人工智能的思考与展望

近些年来&#xff0c;人工智能的话题一次次的冲上热榜&#xff0c;而在前段时间内&#xff0c;chatgpt以及midjourney又一次冲上了热搜&#xff0c;在海内外引起广泛的讨论&#xff0c;我个人在研究了近一个多月的技术文档和文献资料后&#xff0c;也对人工智能的未来有了很多的…

STC32G 单片机通用串行通信接口及其编程

STC32G 系列单片机有4个全双工通用串行通信接口&#xff0c;串口1与串口2既有异步通信功能、又有同步通信功能&#xff0c;串口1与串口2都可进行SPI通信&#xff0c;SPI是一个全双工高速同步串行&#xff1b;通信总线串口3、串口4只有异步通信功能。本文将重点讨论其异步通信&a…

hexo个人博客搭建+butterfly主题配置(雏形版本)

前提&#xff1a; 1. 有一个属于自己的GitHub账号 2. 安装好了git 3. 安装好了node 一、安装hexo 1. 建立一个文件夹 Blog&#xff08;可以自己取名字&#xff09;&#xff0c;进入文件夹标右键打开 Git Bush Here&#xff0c;安装Hexo&#xff1a; npm install -g hexo-…

中智股份冲刺上交所上市:半年收入约87亿元,计划募资37亿元

近日&#xff0c;中智经济技术合作股份有限公司&#xff08;下称“中智股份”&#xff09;预披露招股书&#xff0c;准备在上海证券交易所主板上市&#xff0c;中信证券为其保荐机构。 本次冲刺上市&#xff0c;中智经济计划募资37.42亿元&#xff0c;将用于中智人力资源研发运…

函数的连续性和间断点——“高等数学”

各位CSDN的uu们你们好呀&#xff0c;今天小雅兰的内容是高等数学中的函数的连续性和间断点&#xff0c;好的&#xff0c;那现在就让我们进入函数的连续性和间断点的世界吧 一、函数的连续性 1.函数增量 2.连续的定义 3.单侧连续 二、例题&#xff08;函数的连续性&#xff09; …

JDK动态代理CGLIB动态代理

代理模式 是通过代理对象访问目标对象&#xff0c;这样可以在目标对象基础上增强额外的功能&#xff0c;如添加权限&#xff0c;访问控制和审计等功能。 房产中介代替业主卖房 静态代理 静态代理中代理类与被代理类都需要实现同一个接口&#xff0c;这就说明我们的一个静态代…

MFC|Toolbox内控件简单介绍

参考&#xff1a; MFC控件工具箱 &#xff08;https://blog.csdn.net/Hubz131/article/details/77684910&#xff09; 对应工具的超链接是本人搜到认为较易理解的单个控件介绍。 Pointer&#xff1a;就是普通的鼠标&#xff0c;默认状态Button&#xff1a;按钮&#xff0c;用…

stm32f091芯片的学习总结

摘自芯片手册&#xff08;外加自己的思考&#xff09; 发现网上使用这种芯片的人较少或者说解释这种芯片的电路具体怎么画的人较少&#xff0c;本来想直接借鉴的&#xff0c;发现没有找到&#xff0c;于是我自己来写一篇。 一、概述 该芯片提供标准通信接口(两个i2c&#xf…