C++字符串操作中的陷阱
休对故人思故国,且将新火试新茶。诗酒趁年华。
——《望江南·超然台作》【宋】苏轼
目录
正文:
首先我们要明白出现问题的原因:
1. 缓冲区溢出
2. 错误的字符串声明方式
3. 缺乏对NULL指针的检查
解决方案:
下期预告:C++字符串中的string类操作
上期的最后我们抛出了一个新的问题,那就是如果我们发现目标对象的内存已经不足但我们还是将资源对象拼接到目标对象那里,那么在目标内存那里的内存会有什么变化,会对我们的程序有什么危害。现在就让我们看一看:
正文:
我们来看一下代码实例:
#include<iostream>
using namespace std;
#include<string.h>
const int MAX=14;
int main()
{
char s[MAX]={0};
char n[]={"hello"};
chr m[]={"wello"};
char x[]={"only you can do it "}//1
cout<<strcpy(s,n);
//2
cout<<strcpy(s,m,2);
//3
cout<<strcat(s,m);
//4
cout<<strcat(s,x);//新加入的实例int unsigned len=strlen(s);
for(int i=0;i<strlen(s);++i)
{
cout<<s[i]<<endl;
}
return 0;
}
在昨天的代码中我加入了一个新的字符数组,然后将这个字符数组拼接到s数组中,然后输出这个数组。这个时候问题就出现了,我们可以看到在第三步结束时我们的数组s所剩的存储空间还有4个位,但是我们的资源数组(x)的长度远远超过4,所以这个时候就会出现一个问题,那就是数据溢出。我们要知道数据溢出之后就会向后填充溢出的部分,但是这个数组之后的空间存储了其他的数据。这就是说溢出的数据会替换掉下一个位置原本的数据。(比如:我们s数组之后存储的是数组a,那么s数组溢出的数据就会侵占原本a数组中元素的位置,导致a数组的存储内容出现问题。)
这个问题十分的严重,因为一不小心就会导致整个项目出现bug无法运行,尤其可怕的是这种溢出系统是不会报错的,也就是说会在我们不知道的情况下出错。如果是个巨大的项目,那么就是一个十分棘手的bug。
首先我们要明白出现问题的原因:
strcat这类的函数在C语言等编程语言中,用于将两个字符串连接起来,即将源字符串(src)拼接到目标字符串(dest)的末尾。然而,这类函数存在安全缺陷,主要原因包括:
1. 缓冲区溢出
- 根本原因:strcat函数没有检查目标字符串(dest)的空间是否足够以容纳源字符串(src)。如果dest所指向的缓冲区大小不足以容纳两个字符串连接后的结果,那么strcat会继续在dest的原始内存区域之后写入数据,直到src的末尾。这会导致缓冲区溢出,可能覆盖相邻内存区域的数据,引发程序崩溃或安全漏洞。
- 危害:缓冲区溢出是许多安全漏洞的根源,攻击者可以利用这一漏洞执行任意代码、提升权限或绕过安全机制。
2. 错误的字符串声明方式
- 在使用strcat时,如果目标字符串是通过指针指向一个字符串常量(如
char *dest = "initial";
),则尝试修改这个字符串(即拼接新内容)将导致未定义行为,因为字符串常量通常存储在只读内存区域。 - 正确的做法是使用字符数组(如
char dest[SIZE] = "initial";
)来确保有足够的空间进行字符串操作,并且该数组是可修改的。
3. 缺乏对NULL指针的检查
- 如果strcat的任一参数为NULL,其行为是未定义的。在实际使用中,应该检查指针的有效性,以避免潜在的空指针解引用错误。(主要原因)
解决方案:
所以C++有了这类函数的升级版,更加的安全:
strnlen_s,strcpy_s,strncpy_s,strcat_s等几个函数
请看优化后的代码:
/*#include<iostream>
using namespace std;
#include<string.h>
#include<cstring>
const int MAX=12;
int main()
{
char s[MAX]={0};
char n[]={"hello"};
char m[]={"wello"};
//cout<<strcpy(s,n);
cout<<strcpy_s(s,MAX,n) << endl;
//cout<<strcpy(s,n,2);
cout<<strcpy_s(s,MAX,n,2);
//cout<<strcat(s,m);
cout<<strcat_s(s,MAX,m);unsigned int len=strlen(s);
for(int i=0;i<len;++i)
{
cout<<s[i]<<endl;
}
return 0;
}
*/#include<iostream>
using namespace std;
#include<string.h>
#include<cstring>const int MAX=12;int main()
{char s[MAX]={0};char n[]={"hello"};char m[]={"wello"};// 使用strncpy来安全地复制字符串strncpy(s, n, MAX);s[MAX-1] = '\0'; // 确保字符串以null终止cout << s << endl;// 使用strncat来安全地连接字符串strncat(s, m, MAX-strlen(s)-1);//求出剩余内存的长度s[MAX-1] = '\0'; // 确保字符串以null终止cout << s << endl;unsigned int len = strlen(s);for(unsigned int i=0; i<len; ++i){cout << s[i] << endl;}return 0;
}
一些第三方库提供了额外的安全函数,这些函数通过检查边界和提供其他保护措施来增强C的安全性。例如,Microsoft的C运行时库(CRT)提供了安全版本的函数,如
strcpy_s
。(部分编译器可能无法使用)
这里说明一下,代码中其实我列了两种的方式,第一种可能会在编译器中无法通过,所以我又写了第二种方式,这种方式也是可以的,不过就是要自己对结尾加上一个结束符,这就考验编写者的个人细心程度了,所以这种办法也不是很常用,因此在C++中又诞生了一种更简单的,更安全的方法那就是string类里的函数(比如:strlcpy)。
这些代码很简单没什么要特殊注意的,自己记住这些格式就没问题,只需要记住最原始的strcpy之类的函数是没有自动停止的功能,会产生一些隐藏的bug,有这个意识就可以了,即使对此有了完整的技术可以杜绝这种隐患,但是我们还是要保持这种意识,对我们写代码有帮助。
下期我们就来讲一下string类里的相关操作。
🆗到这里,这篇关于:C++字符串操作中的陷阱就说完了,求一个免费的赞,感谢阅读。
下期预告:C++字符串中的string类操作
相关文章:
C++字符串操作中的陷阱
休对故人思故国,且将新火试新茶。诗酒趁年华。 ——《望江南超然台作》【宋】苏轼 目录 正文: 首先我们要明白出现问题的原因: 1. 缓冲区溢出 2. 错误的字符串声明方式 3. 缺乏对NULL指针的检查 解决方案: 下期预告:C字符串…...
最值求解 | 管理类联考数学专项
日期内容2024.9.5新建2024.9.6曦曦求最值完结 实数求最值至少至多抽屉原理工程问题线性规划一次性绝对值求最值 参考: b站跟着曦曦老师玩转【最值】...

C++_继承详解
继承的概念 继承(inheritance)机制是面向对象程序设计使代码可以复用的重要的手段,它允许程序员在保持原有类特性的基础上进行扩展,增加功能。继承呈现了面向对象程序设计的层次结构,之前我们接触的复用都是函数复用,今天我们所讨…...
区块链开发解决方案有哪些
区块链开发解决方案概述 区块链开发解决方案旨在利用区块链技术构建和开发新型应用和系统,以解决各种业务问题和提升效率。区块链作为一种基于密码学的分布式账本技术,通过将交易和数据记录在不可篡改的区块中,并通过网络中的多个节点共同验…...
Express与SQLite集成教程:轻松实现数据库操作
Express使用SQLite的教程可以大致分为以下几个步骤。以下是一个详细的指南,帮助你在Express项目中集成SQLite数据库。 1. 安装必要的库 首先,你需要在你的Express项目中安装sqlite3库。打开终端或命令提示符,切换到你的项目目录,…...

Transforms的常见用法
文章目录 一、封装函数与普通函数的用法区别二、Image.open()打开图片的格式三、ToTensor打开图片格式四、ToTensor使用五、Normalize归一化使用六、Resize的使用七、Compose - Resize 使用八、RandomCrop() 随机裁剪用法 一、封装函数与普通函数的用法区…...
js 创建 React 项目
起因(目的): js 很久没写了。 react js 之前粗略看过, 最近又需要用到, 继续学习, 记录 积累。 1. 新建 React 项目 的几种方法。 官方建议使用 next 来创建 React 项目, 但是我觉得太复杂了。以后再看看. npx create-next-applatest # !!! 不建议使…...
WPF 中常用 `Transform` 类的介绍、使用示例和适用场景
WPF 中常用 Transform 类的介绍、使用示例和适用场景 使用场景解释代码示例示例代码解释 Transform 类描述使用示例适用场景TranslateTransform用于沿 X 轴或 Y 轴平移(移动)元素。xml <TranslateTransform X"50" Y"100" />移…...
ElasticSearch-DSL
查询所有 match_all 分页查询 from size深分页查询 Scroll指定字段排序 sort返回指定字段_sourcematch 短语查询 match_phrase多字段查询 multi_matchquery_string simple_query_string 关键词查询 Term 结构化搜索 前缀查询 prefix通配符查询 wildcard范围查询 range多 id 查…...

Learn ComputeShader 07 Post Processing
这次我们将使用计算机着色器对图像进行后处理。 要进行后处理需要将渲染图像从cpu传递给gpu,并在gpu对图像进行处理然后传回cpu。 首先创建一个后处理基类BasePP 首先声明需要用到的属性。 using System.Collections; using System.Collections.Generic; using …...

初始QT!
作业:了解QT文件夹初始代码的意义 QT core gui #QT工程所需得类库 core是核心库 gui图形化界面相关库类 greaterThan(QT_MAJOR_VERSION, 4): QT widgets #版本超过4.0会加上widgetsCONFIG c11 #该编辑器支持c11后的版本 # The following define makes you…...

全国大学生数据建模比赛——深度学习
全国大学生数学建模比赛中,深度学习可以成为解决复杂问题的有力手段。 一、深度学习的优势在比赛中的体现 强大的模式识别能力:深度学习模型,如卷积神经网络(CNN)和循环神经网络(RNN)࿰…...

Qt技巧(二)-滑动界面,轮询控件,循环操作控件
在Qt界面开发过程中,我们常常要对同类部件,具有同样功能的一系列部件进行操作,比如: 这个页面该怎么设计,中间的几个选项该怎么操作? 我们在主工程中添加一个设计师界面类,类名设置为“BrandF…...

003——单链表
1.链式存储的特点 逻辑(通过指针实现)上相邻,物理上可相邻可不相邻 2.结点(节点都可以) 4(&8) 8(&6) 6(&1) 1(&…...
XILINX平台下LINUX DMA驱动调研
专栏目录 高质量文章导航-持续更新中-CSDN博客 基础概念 VA:virtual address称为虚拟地址, PA:physical address称为物理地址。 CPU通过地址来访问内存中的单元,如果CPU没有MMU,或者有MMU但没有启动,那么CPU内核在取指令或者访问内存时发出的地址(此时必须是物理地址…...
Oracle数据库安装和配置指南
Oracle数据库是一款功能强大的企业级关系数据库管理系统(RDBMS),广泛应用于各种规模的企业和组织。其强大的性能和丰富的功能使其成为数据库管理的首选解决方案之一。以下是关于如何安装和配置 Oracle 数据库的详细指南。 一、准备工作 在开…...

制造业中工艺路线(工序)与产线(工作中心)关系
一.工艺路线与生产线是数字孪生中的虚实关系: 1.工艺路线为虚,生产线体为实; 2.工艺路线指导生产线的生产组织,生产线承载工艺路线的能力,把虚拟的生产信息流变成真实的产流。 二.工艺路线与生产线是数字孪生中互为“…...
目标跟踪算法——ByteTrack算法原理解析
文章目录 ByteTrack1. ByteTrack算法步骤:2. 算法解释2.1 模型初始化2.2 模型更新算法流程2.2.1 检测结果划分,划分为高分和较低分段2.2.2 高分段处理手段2.2.3 最优匹配与未匹配划分2.2.4 低分框再匹配2.2.5 未确认轨迹处理2.2.6 更新状态 2.3 匈牙利匹…...

C语言编译的过程
文章目录 1. 预处理(Preprocessing)2. 编译(Compilation)3. 汇编(Assembly)4. 链接(Linking)总结 c语言通过编译器直接编译成机器语言程序。 C语言程序的编译过程通常分为四个主要步…...

前端面试题——栈与队列、动态路由、链表
栈、队列与链表 Java数据结构栏目总结-CSDN博客 栈(Stack) 栈是一种后进先出(LIFO, Last In First Out)的数据结构。它只允许在栈顶进行添加(push)或删除(pop)元素的操作。 基本操…...
Cursor实现用excel数据填充word模版的方法
cursor主页:https://www.cursor.com/ 任务目标:把excel格式的数据里的单元格,按照某一个固定模版填充到word中 文章目录 注意事项逐步生成程序1. 确定格式2. 调试程序 注意事项 直接给一个excel文件和最终呈现的word文件的示例,…...
蓝桥杯 2024 15届国赛 A组 儿童节快乐
P10576 [蓝桥杯 2024 国 A] 儿童节快乐 题目描述 五彩斑斓的气球在蓝天下悠然飘荡,轻快的音乐在耳边持续回荡,小朋友们手牵着手一同畅快欢笑。在这样一片安乐祥和的氛围下,六一来了。 今天是六一儿童节,小蓝老师为了让大家在节…...
基础测试工具使用经验
背景 vtune,perf, nsight system等基础测试工具,都是用过的,但是没有记录,都逐渐忘了。所以写这篇博客总结记录一下,只要以后发现新的用法,就记得来编辑补充一下 perf 比较基础的用法: 先改这…...

相机从app启动流程
一、流程框架图 二、具体流程分析 1、得到cameralist和对应的静态信息 目录如下: 重点代码分析: 启动相机前,先要通过getCameraIdList获取camera的个数以及id,然后可以通过getCameraCharacteristics获取对应id camera的capabilities(静态信息)进行一些openCamera前的…...

新能源汽车智慧充电桩管理方案:新能源充电桩散热问题及消防安全监管方案
随着新能源汽车的快速普及,充电桩作为核心配套设施,其安全性与可靠性备受关注。然而,在高温、高负荷运行环境下,充电桩的散热问题与消防安全隐患日益凸显,成为制约行业发展的关键瓶颈。 如何通过智慧化管理手段优化散…...

自然语言处理——循环神经网络
自然语言处理——循环神经网络 循环神经网络应用到基于机器学习的自然语言处理任务序列到类别同步的序列到序列模式异步的序列到序列模式 参数学习和长程依赖问题基于门控的循环神经网络门控循环单元(GRU)长短期记忆神经网络(LSTM)…...
什么?连接服务器也能可视化显示界面?:基于X11 Forwarding + CentOS + MobaXterm实战指南
文章目录 什么是X11?环境准备实战步骤1️⃣ 服务器端配置(CentOS)2️⃣ 客户端配置(MobaXterm)3️⃣ 验证X11 Forwarding4️⃣ 运行自定义GUI程序(Python示例)5️⃣ 成功效果
零基础在实践中学习网络安全-皮卡丘靶场(第九期-Unsafe Fileupload模块)(yakit方式)
本期内容并不是很难,相信大家会学的很愉快,当然对于有后端基础的朋友来说,本期内容更加容易了解,当然没有基础的也别担心,本期内容会详细解释有关内容 本期用到的软件:yakit(因为经过之前好多期…...

七、数据库的完整性
七、数据库的完整性 主要内容 7.1 数据库的完整性概述 7.2 实体完整性 7.3 参照完整性 7.4 用户定义的完整性 7.5 触发器 7.6 SQL Server中数据库完整性的实现 7.7 小结 7.1 数据库的完整性概述 数据库完整性的含义 正确性 指数据的合法性 有效性 指数据是否属于所定…...
Mysql8 忘记密码重置,以及问题解决
1.使用免密登录 找到配置MySQL文件,我的文件路径是/etc/mysql/my.cnf,有的人的是/etc/mysql/mysql.cnf 在里最后加入 skip-grant-tables重启MySQL服务 service mysql restartShutting down MySQL… SUCCESS! Starting MySQL… SUCCESS! 重启成功 2.登…...