【C】错误的变量定义导致sprintf()‌输出错误

问题描述

刚刚写一个用AT指令透传相关的函数,需要用到sprintf()‌拼接字符串。
结果发现sprintf()‌拼接出来的内容是错误的,简化后的代码如下:

const char AT_CIPSEND_FIX_LENGTH_HEADER[11] = "AT+CIPSEND=";	// 错误的!!!	
const char AT[] = "AT\r\n";void ESP8285_CipSend_FixLength(char* data, uint8_t length)
{static char AT_CIPSEND_FIX_LENGTH_FRALME[16] = {0};sprintf(AT_CIPSEND_FIX_LENGTH_FRALME, "%s", AT_CIPSEND_FIX_LENGTH_HEADER);
}

简化后的代码其实就是把AT_CIPSEND_FIX_LENGTH_HEADER的内容打印到AT_CIPSEND_FIX_LENGTH_FRALME里面,结果一看AT_CIPSEND_FIX_LENGTH_FRALME里面出现了多余的内容。
在这里插入图片描述
很显然,多余的内容就是AT_CIPSEND_FIX_LENGTH_HEADER字符串后面的内容,即AT字符串的内容。

问题原因

问题的原因其实很简单,AT_CIPSEND_FIX_LENGTH_HEADER字符串长度是11位的,没有把作为字符串结尾的\0算进去

因此在用sprintf()‌的时候,没有正确的找到字符串的结尾,把内存后面AT字符串的结尾当成字符串的结尾了,所以spinrtf()‌的输出结果是两个字符串的拼接

正确改法1

可以改写成如下:

const char AT_CIPSEND_FIX_LENGTH_HEADER[12] = "AT+CIPSEND=";	// 指定长度为12
const char AT[] = "AT\r\n";
void ESP8285_CipSend_FixLength(char* data, uint8_t length)
{static char AT_CIPSEND_FIX_LENGTH_FRALME[16] = {0};sprintf(AT_CIPSEND_FIX_LENGTH_FRALME, "%s", AT_CIPSEND_FIX_LENGTH_HEADER);
}

在这里插入图片描述

正确改法2

也可以直接不指定长度,改写如下:

const char AT_CIPSEND_FIX_LENGTH_HEADER[] = "AT+CIPSEND=";		// 不指定长度	
const char AT[] = "AT\r\n";void ESP8285_CipSend_FixLength(char* data, uint8_t length)
{static char AT_CIPSEND_FIX_LENGTH_FRALME[16] = {0};sprintf(AT_CIPSEND_FIX_LENGTH_FRALME, "%s", AT_CIPSEND_FIX_LENGTH_HEADER);
}

在这里插入图片描述

错误改法!!!

但这个问题很容易被掩盖,因为像如下这么写结果可能也是对的(取消掉const,长度是11),但其实是错误的!在某些情况下会出错!!:

char AT_CIPSEND_FIX_LENGTH_HEADER[11] = "AT+CIPSEND=";		// 错误的!!
const char AT[] = "AT\r\n";void ESP8285_CipSend_FixLength(char* data, uint8_t length)
{static char AT_CIPSEND_FIX_LENGTH_FRALME[16] = {0};sprintf(AT_CIPSEND_FIX_LENGTH_FRALME, "%s", AT_CIPSEND_FIX_LENGTH_HEADER);
}

在之前的写法中,两个字符串都是常量,在常量存储区,存储位置是连续的。

如果把第一个字符串的const修饰去掉,那么AT_CIPSEND_FIX_LENGTH_HEADER在全局变量存储区,会被加载到内存中,而AT字符串则在常量存储区,这时候两个变量就不是连续的了,因此不会出现“spinrtf()‌的输出结果是两个字符串的拼接”的情况了。
在这种情况下,sprintf()‌的输出结果就取决于什么时候碰到\0了。

所以使用sprintf()‌有缓冲区溢出的风险,可以使用snprintf()‌ ,其接受一个额外的参数size,用于指定目标缓冲区的大小。它在写入时会限制写入的长度,以避免缓冲区溢出,更安全。

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

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

相关文章

【Pytest+Yaml+Allure】实现接口自动化测试框架

一、框架思想 requestsyamlpytestallure实现接口自动化框架。结合数据驱动和分层思想,将代码与数据分离,易维护,易上手。使用yaml编写编写测试用例,利用requests库发送请求,使用pytest管理用例,allure生成…

内网渗透横向移动1

1.信息收集 (1)判断域控 shell net time /domain shell ping OWA2010CN-God.god.org (2)主机探测 浏览探测->网络探测 主机列表显示: (3)域用户收集: shell net user /domain…

C++初阶——类和对象(下)

目录 1、再探构造函数——初始化列表 2、类型转换 3、static成员 4、友元 5、内部类 6、匿名对象 7、对象拷贝时编译器的优化(了解) 1、再探构造函数——初始化列表 1. 构造函数初始化除了使用函数体内赋值,还有一种方式——初始化列表, 初始化列…

数据指标与标签在数据分析中的关系与应用

导读:分享数据指标体系的文章很多,但讲数据标签的文章很少。实际上,标签和指标一样,是数据分析的左膀右臂,两者同样重要。实际上,很多人分析不深入,就是因为缺少对标签的应用。今天系统的讲解下…

Exploring Prompt Engineering: A Systematic Review with SWOT Analysis

文章目录 题目摘要简介方法论背景相关工作评估结论 题目 探索快速工程:基于 SWOT 分析的系统评价 论文地址: https://arxiv.org/abs/2410.12843 摘要 在本文中,我们对大型语言模型 (LLM) 领域的提示工程技术进行了全面的 SWOT 分析。我们强…

Android 常用命令和工具解析之内存相关

目录 1 基本概念 1.1 PSS & RSS & USS & VSS 1.1.1 PSS 1.1.2 RSS 1.2 Dirty & Clean & SwapPss 1.2.1 Private Dirty 1.2.2 Private Clean 1.2.3 SwapPss Dirty 1.3 Swap & buffers & cache 1.3.1 Swap 1.3.2 buffers 1.3.3 cache 2…

使用Go 语言连接并操作 MySQL 数据库

新建项目,我这里使用的vscode: 1.新建项目初始化: 手动创建工程文件夹go安装目录->src->projectName 在项目下创建 main.go文件: 在vscode中点击文件->打开文件夹,选择刚刚新建的文件夹。打开后&#xff0…

YOLOv11融合[NeurlS2022]递归门控卷积gnconv模块及相关改进思路

YOLOv11v10v8使用教程: YOLOv11入门到入土使用教程 YOLOv11改进汇总贴:YOLOv11及自研模型更新汇总 《HorNet: Efficient High-Order Spatial Interactions with Recursive Gated Convolutions》 一、 模块介绍 论文链接:https://arxiv.org…

从零开始-VitePress 构建个人博客上传GitHub自动构建访问

从零开始-VitePress 构建个人博客上传GitHub自动构建访问 序言 VitePress 官网:VitePress 中文版 1. 什么是 VitePress VitePress 是一个静态站点生成器 (SSG),专为构建快速、以内容为中心的站点而设计。简而言之,VitePress 获取用 Markdown…

使用Notepad++工具去除重复行

使用Notepad工具去除重复行 参考链接:https://blog.csdn.net/londa/article/details/108981396 一 、使用正则表达式 1、对文本进行排序,让重复行排在一起 2、使用正则表达式替换(注意)^(.*?)$\s?^(?.*^\1$) 在替换时选择正…

RabbitMQ和RocketMQ相关面试题

RabbitMQ和RocketMQ面试题 RabbitMQ1.RabbitMQ各部分角色2.如何确保RabbitMQ消息的可靠性?3.什么样的消息会成为死信?4.死信交换机的使用场景是什么?5.TTL6.延迟队列7.消息堆积问题8.MQ集群 RocketMQ1.RocketMQ各部分角色2.RocketMQ如何保证高…

【机器学习chp5】线性回归

推荐文章1,三种角度详细分析了L1,L2正则化的本质。 【王木头 L1、L2正则化】三个角度理解L1、L2正则化的本质-CSDN博客 推荐文章2,其中有各种梯度下降的优化算法分析。 【王木头梯度下降法优化】随机梯度下降、牛顿法、动量法、Nesterov、…

【AI系统】GPU 架构回顾(从2018年-2024年)

Turing 架构 2018 年 Turing 图灵架构发布,采用 TSMC 12 nm 工艺,总共 18.6 亿个晶体管。在 PC 游戏、专业图形应用程序和深度学习推理方面,效率和性能都取得了重大进步。相比上一代 Volta 架构主要更新了 Tensor Core(专门为执行…

Windows11深度学习环境配置

CUDA、CUDNN 一、安装另一个版本的CUDA 下载.exe文件,网址打不开自己开热点就能解决:CUDA Toolkit 11.2 Downloads | NVIDIA Developer 若遇到“You already have a newer version of the NVIDIA Frameview SDK installed” 1.把电脑已经存在的FrameVi…

H.265流媒体播放器EasyPlayer.js H5流媒体播放器关于如何查看手机端的日志信息并保存下来

现今流媒体播放器的发展趋势将更加多元化和个性化。人工智能的应用将深入内容创作、用户体验优化等多个方面,带来前所未有的个性化体验。 EasyPlayer.js H.265流媒体播放器属于一款高效、精炼、稳定且免费的流媒体播放器,可支持多种流媒体协议播放&#…

力扣.5.最长回文子串力扣.14最长公共前缀力扣219.存在重复元素II力扣.67二进制求和

目录 力扣.5.最长回文子串 力扣.14最长公共前缀 力扣219.存在重复元素II 力扣.67二进制求和 力扣.5.最长回文子串 中心拓展算法,假设以i位置为中心两边可以扩展到多少,所以当对应一个中间位置的时候,可以定义两个指针,对应一个…

Vue.js 插槽 Slots 实际应用 最近重构项目的时候遇到的...

前端开发中 插槽 Slots 是一个重要的概念 我们可以查看一下vue.js的官方文档 https://cn.vuejs.org/guide/components/slots 类似于连接通道一样 可以把核心代码逻辑搬到另外的地方 做一个引用 而原先的地方可能并不能这样书写 对于这个概念我在vue的官方文档里面找到了…

快速识别模型:simple_ocr,部署教程

快速识别图片中的英文、标点符号、数学符号、Emoji, 模型会输出图片中文字行的坐标位置、最低得分、识别结果。当前服务用到的模型:检测模型、数字识别、英文符号识别。 一、部署流程 1.更新基础环境 apt update2.安装miniconda wget https://repo.anaconda.com/…

Android mk/bp构建工具介绍

零. 前言 由于Bluedroid的介绍文档有限,以及对Android的一些基本的知识需要了(Android 四大组件/AIDL/Framework/Binder机制/JNI/HIDL等),加上需要掌握的语言包括Java/C/C等,加上网络上其实没有一个完整的介绍Bluedroid系列的文档&#xff0…

docker安装使用Elasticsearch,解决启动后无法访问9200问题

1.docker安装、启动es docker pull elasticsearch:8.13.0docker images启动容器 docker run -d -p 9200:9200 -p 9300:9300 -e ES_JAVA_OPTS"-Xms256m -Xmx256m" --name es01 8ebd258614f1-d 后台运行-p 9200:9200 -p 9300:9300 开放与主机映射端口-e ES_JAVA_OPTS…