[C/C++内存安全]_[中级]_[安全处理字符串]

场景

  1. 在现代C++开发指南出来后,并不建议使用C的某些内存不安全的字符串处理函数。那么有哪些函数不安全?

说明

  1. 内存安全方面,肯定是要向Rust看齐的。使用标准std::string字符串类,很大情况能避免缓冲区溢出问题。

  2. 如果旧项目里有用到以下的这些C字符串函数,那么最好用std::string改写吧。

    • strcpy: 不要使用.strcpy,目标缓冲区没有设置最大接收的大小,容易造成缓冲区溢出。strcpy最后会复制源缓冲区的\0到目标缓冲区末尾,前提是目标缓冲器有足够的大小。

    • strcat: 不要使用. 只是在目标缓冲区的0位置开始添加新的字符串。目标缓冲区没有设置最大接收的大小,容易造成缓冲区溢出。strcat最后会复制源缓冲区的\0到目标缓冲区末尾,前提是目标缓冲器有足够的大小。

    • sprintf: 不要使用. 目标缓冲区没有设置最大接收的大小,容易造成缓冲区溢出。sprintf最后会复制源缓冲区的\0`到目标缓冲区末尾,前提是目标缓冲器有足够的大小。

    • strncpy: 不要使用. 目标缓冲区没有设置最大接收的大小,容易造成缓冲区溢出。·strncpy·最后不会复制一个结束符到目标缓冲区,如果目标缓冲区不是以0结尾,那么在读取目标缓冲区时也会读取越界。

    • strncat: 不要使用.strncat 目标缓冲区没有设置最大接收的大小,容易造成缓冲区溢出。·strncat·最后会复制源缓冲区的\0到目标缓冲区末尾,前提是目标缓冲器有足够的大小。

  3. strcpy,strcat,strncpystrncat可以使用std::string代替;sprintf可以使用snprintf或者stringstream代替。

例子

  1. 以下例子使用这些危险的C函数处理字符串,并使用std::stringstringstream来替换之。
#include <iostream>
#include <string.h>
#include <string>
#include <iostream>
#include <sstream>
#include <iomanip>using namespace std;void TestUnsafeCStringFunc()
{const int kBufSize = 32;char buf[kBufSize] = {0};string str;// 30个字符const char kStr[] = "http://blog.csdn.net/infoworld";constexpr int kStrSize = sizeof(kStr) - 1;// 1. 不要使用.`strcpy`,目标缓冲区没有设置最大接收的大小,容易造成缓冲区溢出。//  -- `strcpy`最后会复制源缓冲区的`\0`到目标缓冲区末尾,前提是目标缓冲器有足够的大小。strcpy(buf, kStr);cout << "strcpy: " << buf << endl;//  -- 使用`string`的代替.str.append(kStr);cout << "string: " << str << endl;// 2. 不要使用.同`strcpy`,只是在目标缓冲区的`0`位置开始添加新的字符串。目标缓冲区没有设置最大接收的大小,容易造成缓冲区溢出。//  -- `strcat`最后会复制源缓冲区的`\0`到目标缓冲区末尾,前提是目标缓冲器有足够的大小。memset(buf, 0, sizeof(buf));strcat(buf, kStr);strcat(buf, "/");cout << "strcat: " << buf << endl;//  -- 使用`string`的代替.str.clear();str.append(kStr);str.append("/");cout << "string: " << str << endl;// 3. 不要使用. 目标缓冲区没有设置最大接收的大小,容易造成缓冲区溢出。//  -- `sprintf`最后会复制源缓冲区的`\0`到目标缓冲区末尾,前提是目标缓冲器有足够的大小。sprintf(buf, "%d-%.2d-%.2d", 2025, 7, 22);cout << "sprintf: " << buf << endl;// -- 方法1:使用`stringstream`代替stringstream ss;ss << 2025 << "-" << std::setw(2) << std::setfill('0') << 7 << "-"<< std::setw(2) << std::setfill('0') << 22;str = ss.str();cout << "stringstream: " << str << endl;// -- 方法2: 使用`snprintf`代替.// -- 安全,指定目标缓冲区大小,最多指定目标缓冲区大小`-1`个字符被写入,之后会添加一个结束符。// -- 如果`buf`为`NULL`,并且目标缓冲区大小为`0`时,返回写源字符串所需要的总大小, 不包括结束符。snprintf(buf,sizeof(buf),"%d-%.2d-%.2d", 2025, 7, 22);cout << "snprintf: " << buf << endl;auto number = snprintf(NULL,0,"%d-%.2d-%.2d", 2025, 7, 22);cout << "snprintf number: " << number << endl;auto myBuf = (char*)malloc(number+1);sprintf(myBuf,"%d-%.2d-%.2d", 2025, 7, 22);cout << "myBuf: " << myBuf << endl;free(myBuf);// 4. 不要使用. `strncpy` 目标缓冲区没有设置最大接收的大小,容易造成缓冲区溢出。// -- ·strncpy·最后不会复制一个结束符到目标缓冲区,如果目标缓冲区不是以`0`结尾,那么在读取目标缓冲区时也会读取越界。memset(buf, 0, sizeof(buf));strncpy(buf, kStr, kStrSize);cout << "strncpy: " << buf << endl;// -- 同上,还是使用`std::string`代替。// 5. 不要使用. `strncat` 目标缓冲区没有设置最大接收的大小,容易造成缓冲区溢出。// -- ·strncat·最后会复制源缓冲区的`\0`到目标缓冲区末尾,前提是目标缓冲器有足够的大小。buf[kBufSize - 1] = '1'; // 测试最后添加一个`1`字符,调用`strncat`后会使用`0`把它覆盖。strncat(buf, "/", 1);cout << "strncat: " << buf << endl;// -- 同上,还是使用`std::string`代替。
}int main()
{std::cout << "Hello World!\n";std::cout << "=========== TestUnsafeCStringFunc =========!\n";TestUnsafeCStringFunc();
}

输出

Hello World!
=========== TestUnsafeCStringFunc =========!
strcpy: http://blog.csdn.net/infoworld
string: http://blog.csdn.net/infoworld
strcat: http://blog.csdn.net/infoworld/
string: http://blog.csdn.net/infoworld/
sprintf: 2025-07-22
stringstream: 2025-07-22
snprintf: 2025-07-22
snprintf number: 10
myBuf: 2025-07-22
strncpy: http://blog.csdn.net/infoworld
strncat: http://blog.csdn.net/infoworld/

参考

  1. strcpy

  2. strcat

  3. strncpy

  4. strncat

  5. sprintf,snprintf

  6. stringstream

  7. string

  8. C++11语言特性和标准库

  9. 如何实现std::string自己的Format(sprintf)函数

  10. 避免使用wsprintf函数

  11. setw

  12. setfill

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

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

相关文章

【CNN】卷积神经网络- part1

1.卷积1.局部连接定义&#xff1a;只是于输入数据的一部分区域相连&#xff0c;每个神经元只关注一小部分作用&#xff1a;模仿人类的视野机制&#xff0c;极大的减少了模型参数的数量&#xff0c;降低了计算成本2.权重共享定义&#xff1a;所有神经元使用相同的权重向量来检测…

漏洞生命周期管理:从发现到防护的全流程方案

漏洞并非孤立存在&#xff0c;而是遵循 “发现→评估→修复→验证→闭环” 的生命周期。多数企业安全事件的根源并非缺乏漏洞发现能力&#xff0c;而是对漏洞生命周期的管理缺失 —— 大量漏洞被发现后长期未修复&#xff0c;或修复后未验证效果。构建全流程漏洞生命周期管理体…

opencv图像基本操作解析与实操

图片操作cv2.namedWindow() 创建命名窗口cv2.imshow()显示窗口cv2.destroyAllwindws()摧毁窗口cv2.resizeWindow()改变窗口大小cv2.waitKey()等待用户输入cv2.imread()读取图像img.shape 图片h、w、c&#xff08;高、宽、通道数import cv2 # opencv读取的格式是BGR import m…

kafka--基础知识点--6.1--LEO、HW、LW

在 Apache Kafka 中&#xff0c;LEO&#xff08;Log End Offset&#xff09;、HW&#xff08;High Watermark&#xff09;、和 LW&#xff08;Low Watermark&#xff09; 是副本机制和日志管理中的核心概念&#xff0c;共同确保数据一致性、可见性和存储效率。以下是它们的详细…

在线深凹槽深检测方法都有哪些 —— 激光频率梳 3D 轮廓检测

引言在制造业中&#xff0c;深凹槽深度的精确检测是保证零部件质量的关键环节。随着智能制造的推进&#xff0c;在线检测需求日益迫切&#xff0c;传统检测方法在效率和精度上的不足逐渐显现。本文将梳理在线深凹槽深的传统检测方法&#xff0c;并重点探讨激光频率梳 3D 轮廓检…

NumPy 数组拼接的高级技巧与实践

在数据处理和机器学习领域&#xff0c;NumPy 是 Python 中最核心的科学计算库之一。NumPy 数组&#xff08;ndarray&#xff09;的拼接操作是数据预处理中极为常见的需求。本文将深入探讨如何将不同形状的 NumPy 数组进行拼接&#xff0c;特别是如何将多个一维数组与二维数组进…

原创-基于 PHP 和 MySQL 的证书管理系统 第三版

第一版属于开源版本&#xff0c;所以后台功能没有开发许多出来&#xff0c;今天分享证书查询第三版&#xff1b; 通过几天的紧急写代码及测试&#xff1b;第三版基本可以上线上&#xff0c;不过后面有一些BUG只能一边修复。 演示地址&#xff1a;物星科云证书管理系统 第三版…

爬虫虚拟环境

conda create --name myrepenv python3.12创建一个名为 myrepenv、Python 版本为 3.12 的全新 Conda 虚拟环境&#xff0c;适合需要隔离依赖或测试不同 Python 版本的项目。我的方式创建(需要指定盘符)conda create --prefixD:\Anaconda3\envs\myrepenv python3.12展示所下的co…

Netty集群方案详解与实战(Zookeeper + Redis + RabbitMQ)

一、背景 二、Netty 单体架构的优缺点 优点 缺点 三、Netty 集群架构的优缺点 优点 缺点 四、适用场景对比 五、Netty单体架构代码实现 六、Netty集群架构方案实现 方案一、Nginx负载均衡实现集群(较为简单) Nginx配置 前端连接方式 方案二、NacosGateway&#xff08;结合…

Oracle迁移到高斯,查询字段默认小写,解决办法

一、问题说明 Oracle中&#xff0c;查询结果字段默认大写。高斯中&#xff0c;查询结果字段默认小写。在Mybatis的xml中&#xff0c;如果查询语句使用Map接收查询结果&#xff0c;使用resultType"java.util.HashMap"或resultType"Map"等写法&#xff0c;返…

Android Jetpack Compose + MVVM 开发流程深度分析

核心组件关系图 [View] -- 观察 --> [ViewModel] -- 操作 --> [Repository]| | Compose UI StateFlow/LiveData| | 用户交互事件 Room/Retrofit| …

Tailwind CSS快速上手 Tailwind CSS的安装、配置、使用

&#x1f4da;前言 在Web前端开发的历史长河中&#xff0c;CSS的编写方式经历了多次演进&#xff0c;从早期的原生CSS 到 CSS预处理(Less/Sass/Stylus) 到 CSS-in-JS(Styled-Components/Emotion) 再到 Utility-First 原子化CSS。每一种演进方案其本质都是围绕“开发效率”、“…

单例模式的智慧:从UVM看控制的艺术

有时候&#xff0c;生活中的很多东西其实只需要一个就够了&#xff0c;就像一个公司只需要一个CEO&#xff0c;一个王朝只需要一个皇帝。在UVM验证环境中&#xff0c;也有很多这样的需求——有些对象&#xff0c;我们希望它在整个仿真过程中只存在一个实例。这就是我们今天要聊…

Hexo - 免费搭建个人博客01 - 安装软件工具

导言我的博客&#xff1a;https://q164129345.github.io/ Hexo 作为一个 Node.js 框架&#xff0c;它依赖于 Node.js 运行时环境来执行。 一、安装Node.js官方网址&#xff1a;https://nodejs.org/zh-cn追求系统稳定性、可靠性以及希望减少维护频率的用户来说&#xff0c;LTS版…

【Kubernetes】集群启动nginx,观察端口映射,work节点使用kubectl配置

参考b站叩丁狼总结&#xff1a;完整版Kubernetes&#xff08;K8S&#xff09;全套入门微服务实战项目&#xff0c;带你一站式深入掌握K8S核心能力 在master节点执行 kubectl create deployment nginx --imagenginxkubectl expose deployment nginx --port80 --typeNodePort1. …

20250704-基于强化学习在云计算环境中的虚拟机资源调度研究

基于强化学习在云计算环境中的虚拟机资源调度研究 随着云计算规模的持续扩大&#xff0c;数据中心虚拟机资源调度面临动态负载、异构资源适配及多目标优化等挑战。传统启发式算法在复杂场景下易陷入局部最优&#xff0c;而深度强化学习&#xff08;DRL&#xff09;凭借序贯决策…

day 33打卡

day 21 常见的降维算法 # 先运行之前预处理好的代码 import pandas as pd import numpy as np import matplotlib.pyplot as plt import seaborn as sns import warnings warnings.filterwarnings(ignore)# 设置中文字体 plt.rcParams[font.sans-serif] [SimHei] plt.rcParam…

sec(x)积分推导

在MATLAB中绘制 sec⁡(x)、cos(x) 和 ln⁡∣sec⁡(x)tan⁡(x)∣的函数图像&#xff0c;需要特别注意 sec⁡(x) 在 cos⁡(x)0&#xff08;即 xπ/2kπ&#xff09;处的奇点。&#xff08;deepseek生成代码&#xff09;% 定义x范围&#xff08;-2π到2π&#xff09;&#xff0c;…

gpt面试题

vue面试题 &#x1f4a1; 一、响应式系统相关 ❓1. Vue 3 的响应式系统是如何实现的&#xff1f;和 Vue 2 有何本质区别&#xff1f; 答案&#xff1a; Vue 3 使用 Proxy 实现响应式&#xff08;位于 vue/reactivity 模块&#xff09;&#xff0c;替代 Vue 2 的 Object.defineP…

【基于OpenCV的图像处理】图像预处理之图像色彩空间转换以及图像灰度化处理

目录 零、写在前面的话 一、图像色彩空间转换 1.1 RGB颜色空间 1.1.1 RGB颜色空间概念 1.1.2 RGB颜色模型​编辑 1.1.3 关于颜色加法 1.1.4 颜色加权加法 1.2 HSV颜色空间 1.2.1 HSV颜色空间概念 1.2.2 HSV颜色模型 1.2.3 应用意义 1.3 颜色转换 1.3.1 转换方法 …