32. C 语言 安全函数( _s 尾缀)
本章目录
- 前言
- 什么是安全函数?
- 安全函数的特点
- 主要的安全函数
- 1. 字符串操作安全函数
- 2. 格式化输出安全函数
- 3. 内存操作安全函数
- 4. 其他常用安全函数
- 安全函数实例
- 示例 1:`strcpy_s` 和 `strcat_s`
- 示例 2:`memcpy_s`
- 示例 3:`strtok_s`
- 总结
前言
在 C 语言的编程中,缓冲区溢出是常见的安全问题之一。它发生在程序尝试将数据写入一个不足够大的缓冲区时,导致数据覆盖了相邻内存区域。这种错误不仅会导致程序崩溃,还可能导致潜在的安全漏洞,使攻击者能够通过精心设计的输入数据控制程序流,甚至执行恶意代码。
为了避免这类问题,C11 标准引入了一些 “安全函数”(通常称为 Annex K 函数),这些函数是传统 C 函数的增强版本,增加了缓冲区大小检查和错误处理机制,从而提升了程序的安全性。
本文将带您深入了解 C 语言中的安全函数,帮助您编写更加健壮和安全的代码。
什么是安全函数?
在 C 语言中,安全函数是指那些在执行字符串和内存操作时,显式检查目标缓冲区大小并报告错误的函数。它们的设计初衷是防止缓冲区溢出、访问越界等问题。安全函数通常返回一个 errno_t
类型的错误码,以便调用者能够检测是否成功执行。
安全函数的特点
- 缓冲区大小检查:安全函数需要明确传递目标缓冲区的大小,确保不会发生溢出。
- 返回值检查:大多数安全函数返回一个错误代码,可以通过检查返回值来判断是否成功执行。
- 错误处理:当缓冲区大小不足或者其他错误发生时,安全函数会尝试清空或初始化输出缓冲区,避免未定义的行为。
主要的安全函数
以下是 C 语言中一些常见的安全函数及其传统函数对比:
1. 字符串操作安全函数
-
strcpy_s
:安全版本的strcpy
,复制字符串并检查目标缓冲区的大小。errno_t strcpy_s(char *dest, rsize_t destsz, const char *src);
-
strcat_s
:安全版本的strcat
,将源字符串追加到目标字符串末尾,并检查缓冲区大小。errno_t strcat_s(char *dest, rsize_t destsz, const char *src);
-
strncpy_s
:安全版本的strncpy
,复制最多n
个字符,并检查缓冲区大小。errno_t strncpy_s(char *dest, rsize_t destsz, const char *src, rsize_t count);
-
strncat_s
:安全版本的strncat
,追加最多n
个字符到目标字符串末尾,并检查缓冲区大小。errno_t strncat_s(char *dest, rsize_t destsz, const char *src, rsize_t count);
-
strtok_s
:安全版本的strtok
,引入上下文参数,解决线程安全问题。char *strtok_s(char *str, const char *delim, char **context);
2. 格式化输出安全函数
-
sprintf_s
:安全版本的sprintf
,格式化输出到字符串时检查缓冲区大小。int sprintf_s(char *buffer, rsize_t sizeOfBuffer, const char *format, ...);
-
snprintf_s
:安全版本的snprintf
,格式化输出时限制字符数并检查缓冲区大小。int snprintf_s(char *buffer, rsize_t sizeOfBuffer, const char *format, ...);
-
vsprintf_s
:安全版本的vsprintf
,接收va_list
参数列表,并检查缓冲区大小。int vsprintf_s(char *buffer, rsize_t sizeOfBuffer, const char *format, va_list argptr);
3. 内存操作安全函数
-
memcpy_s
:安全版本的memcpy
,复制内存时检查目标缓冲区大小。errno_t memcpy_s(void *dest, rsize_t destsz, const void *src, rsize_t count);
-
memmove_s
:安全版本的memmove
,允许内存区域重叠,并检查目标缓冲区大小。errno_t memmove_s(void *dest, rsize_t destsz, const void *src, rsize_t count);
-
memset_s
:安全版本的memset
,填充内存并检查目标缓冲区大小。errno_t memset_s(void *dest, rsize_t destsz, int ch, rsize_t count);
4. 其他常用安全函数
-
_itoa_s
和_ultoa_s
:安全版本的整数转换函数。errno_t _itoa_s(int value, char *buffer, size_t sizeOfBuffer, int radix); errno_t _ultoa_s(unsigned long value, char *buffer, size_t sizeOfBuffer, int radix);
-
_strlwr_s
和_strupr_s
:将字符串转换为小写或大写的安全版本。errno_t _strlwr_s(char *str, size_t numberOfElements); errno_t _strupr_s(char *str, size_t numberOfElements);
安全函数实例
下面通过一些简单的示例,展示如何使用 C 的安全函数来提高代码的健壮性,避免缓冲区溢出问题。
示例 1:strcpy_s
和 strcat_s
#include <stdio.h>
#include <string.h>int main() {char dest[20]; // 目标缓冲区大小为 20const char *src = "Hello, World!";// 使用 strcpy_s 将 src 复制到 destif (strcpy_s(dest, sizeof(dest), src) != 0) {printf("strcpy_s failed!\n");return 1; // 返回错误代码} else {printf("After strcpy_s: %s\n", dest);}// 使用 strcat_s 将 " C Language" 追加到 destconst char *appendStr = " C Language";if (strcat_s(dest, sizeof(dest), appendStr) != 0) {printf("strcat_s failed!\n");return 1; // 返回错误代码} else {printf("After strcat_s: %s\n", dest);}return 0;
}
输出:
After strcpy_s: Hello, World!
strcat_s failed!
在这个示例中,strcpy_s
成功将字符串复制到目标缓冲区,但由于 dest
缓冲区的大小不足以容纳追加的内容,strcat_s
返回错误并防止溢出。
示例 2:memcpy_s
#include <stdio.h>
#include <string.h>int main() {char src[] = "Sensitive Data";char dest[15]; // 目标缓冲区大小为 15// 使用 memcpy_s 将数据复制到 destif (memcpy_s(dest, sizeof(dest), src, strlen(src) + 1) != 0) {printf("memcpy_s failed!\n");return 1; // 返回错误代码} else {printf("After memcpy_s: %s\n", dest);}return 0;
}
输出:
After memcpy_s: Sensitive Data
memcpy_s
确保 dest
缓冲区足够大,以容纳源字符串的所有数据。如果缓冲区不够,函数会返回错误并防止执行不安全的内存复制。
示例 3:strtok_s
#include <stdio.h>
#include <string.h>int main() {char str[] = "apple,orange,banana";char *token;char *context = NULL;// 使用 strtok_s 分割字符串token = strtok_s(str, ",", &context);while (token != NULL) {printf("Token: %s\n", token);token = strtok_s(NULL, ",", &context);}return 0;
}
输出:
Token: apple
Token: orange
Token: banana
在这个例子中,strtok_s
使用上下文参数来避免多线程环境下的安全问题。每次调用都不会影响其他线程中的字符串分割。
总结
C 语言中的安全函数是为了提高代码的安全性而设计的,尤其是在防止缓冲区溢出、内存越界等常见错误方面提供了有效的防护。通过使用这些函数,您可以确保程序在处理字符串和内
相关文章:
32. C 语言 安全函数( _s 尾缀)
本章目录 前言什么是安全函数?安全函数的特点主要的安全函数1. 字符串操作安全函数2. 格式化输出安全函数3. 内存操作安全函数4. 其他常用安全函数 安全函数实例示例 1:strcpy_s 和 strcat_s示例 2:memcpy_s示例 3:strtok_s 总结 …...

Android T(13) 源码分析 — BufferQueue 的分析
Android T(13) 源码分析 — BufferQueue 的分析 文章目录 Android T(13) 源码分析 — BufferQueue 的分析前言摘要一、Java 层的 BufferQueue 分析二、原生层的 BufferQueue 分析1、BLASTBufferQueue 的创建2、BLASTBufferQueue 的更新3、Surface 的创建 总结 前言 该系列文章…...
Vite+TS项目中配置路径别名
在使用 Vite 和 TypeScript 的项目中配置路径别名,可以简化模块导入路径,提高代码的可读性和维护性。以下是详细的步骤和示例代码: 1. 配置 Vite 别名 前置条件 下载types/node 下面引入的path会用到 npm install types/node --save-dev原…...
看盘细节系列 篇二:集合竞价的9点18分大单打到3%以下或以上,9点19分撤单
文章目录 系列文章现象原因分析时间点含义正常情况测试市场反应诱导跟风操纵股价意图系列文章 看盘细节系列 篇一:集合竞价尾盘突变 现象 集合竞价中 9 点 18 分通过一笔大单或连续几笔大单将股价打到 3% 以下或以上,9 点 19 分又迅速撤单。从而在分时图上留下一根长长的上…...

Java继承简介
继承的本质:是代码的复用,重复使用已经定义好的方法和域(即全局变量) 要掌握继承首先要了解Java方法的重载和重写 方法的重载和重写 方法的重载 当前方法名相同,但是参数类型不同,发生重载 类比数学函…...

redis之哨兵集群搭建
一:哨兵集群工作概览图 1.监控:sentinel通过心跳监控redis的master和slave实例是否正常工作 2.故障转移:假如master出现故障,sentinel会选举一个slave作为新的master,当故障实例恢复后身份会变成slave,会以…...

保姆级AI开发环境搭建
目录 windows下环境搭建1. Python环境搭建2. 下载vLLM2.1 安装CUDA2.2 安装Pytorch2.3 安装vllm 3. 部署Deepseek(huggingface)3.1 DeepSeek的优化建议 4. ollama快速部署Deepseek4.1 下载Ollama4.2 配置Ollma4.2 运行模型4.3 其他Ollama命令 linux下环境…...

Arduino 型号的对比
常见 Arduino 型号的对比表格 涵盖了不同型号的关键参数和特点,方便你根据项目需求进行选择: 型号Arduino UnoArduino Mega 2560Arduino LeonardoArduino NanoArduino Due微控制器ATmega328PATmega2560ATmega32U4ATmega328P 或 ATmega168SAM3X8E&#…...
Kafka系列之:定位topic只能保存最新数据的原因
Kafka系列之:定位topic只能保存最新数据的原因 一、背景二、定位排查方向三、深入排查一、背景 kafka topic保存的数据少,topic只能保存最新的数据二、定位排查方向 能想到的定位排查方向:topic能存储的数据量、topic数据保存的时间、topic数据大小./bin/kafka-configs.sh -…...

AtCoder Beginner Contest 391(A~E题题解)
A - Lucky Direction 思路:纯模拟的一个水题 #include <bits/stdc.h> using namespace std; #define int long long string s; signed main() { cin>>s;for(int i0;i<s.size();i){char cs[i];if(cN){cout<<"S";}else if(c…...
mysql mvcc 锁 关系
多版本并发控制(MVCC)是一种用于数据库并发控制的机制,它可以在保证数据一致性的同时,提高数据库的并发性能。下面结合 MVCC 机制,详细阐述常见的四种事务隔离级别(读未提交、读已提交、可重复读、串行化&a…...
安卓手机基于 Termux 安装 AList 并设置开机自启的详细教程
安装 AList 安装 Termux: 点击下载 更新软件包:打开 Termux,运行以下命令以更新软件包列表并升级已安装的软件包: bash复制 pkg update && pkg upgrade安装 AList:运行以下命令安装 AList: bash复…...
LeetCode:503.下一个更大元素II
跟着carl学算法,本系列博客仅做个人记录,建议大家都去看carl本人的博客,写的真的很好的! 代码随想录 LeetCode:503.下一个更大元素II 给定一个循环数组 nums ( nums[nums.length - 1] 的下一个元素是 nums[…...

实验5 配置OSPFv2验证
实验5 配置OSPFv2验证 1.实验目的 (1)OSPFv2 验证的类型和意义。 (2)配置基于区域的 OSPFv2 简单口令验证和 MD5 验证的方法。 (3)配置基于链路的 OSPFv2 简单口令验证和 MD5 验证的方法。 2.实验准备 配置…...

第二节 docker基础之---镜像构建及挂载
查看当前镜像: [rootdocker ~]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE [rootdocker ~]#很明显docker是咱们新搭建的所以目前还没有镜像 1,搜索镜像: [rootdocker ~]# docker search centos 搜索镜像并过滤是官…...

论文阅读:MGMAE : Motion Guided Masking for Video Masked Autoencoding
MGMAE:Motion Guided Masking for Video Masked Autoencoding Abstract 掩蔽自编码(Masked Autoencoding)在自监督视频表示学习中展现了出色的表现。时间冗余导致了VideoMAE中高掩蔽比率和定制的掩蔽策略。本文旨在通过引入运动引导掩蔽策略࿰…...

记录一下 在Mac下用pyinstallter 打包 Django项目
安装: pip install pyinstaller 在urls.py from SheepMasterOneToOne import settings from django.conf.urls.static import staticurlpatterns [path("admin/", admin.site.urls),path(generate_report/export/, ReportAdmin(models.Report, admin.site).generat…...
【漫话机器学习系列】084.偏差和方差的权衡(Bias-Variance Tradeoff)
偏差和方差的权衡(Bias-Variance Tradeoff) 1. 引言 在机器学习模型的训练过程中,我们常常面临一个重要的挑战:如何平衡 偏差(Bias) 和 方差(Variance),以提升模型的泛…...

deepseek本地部署-linux
1、官网推荐安装方法(使用脚本,我绕不过github,未采用) 登录ollama下载网站https://ollama.com/download/linux,linux下有下载脚本。 正常来说,在OS系统下直接执行脚本即可。 2、手动安装方法 2.1获取ol…...
解决使用python提取word文档中所有的图片时图片丢失的问题
python解析word文档,提取文档中所有的图片并保存,并将原图位置用占位符替换。 问题描述 利用python-dox库解析word文档,并提取里面的所有图片时发现会出现一摸一样的图片只解析一次,导致图片丢失,数量不对的情况。 …...

XCTF-web-easyupload
试了试php,php7,pht,phtml等,都没有用 尝试.user.ini 抓包修改将.user.ini修改为jpg图片 在上传一个123.jpg 用蚁剑连接,得到flag...
多模态商品数据接口:融合图像、语音与文字的下一代商品详情体验
一、多模态商品数据接口的技术架构 (一)多模态数据融合引擎 跨模态语义对齐 通过Transformer架构实现图像、语音、文字的语义关联。例如,当用户上传一张“蓝色连衣裙”的图片时,接口可自动提取图像中的颜色(RGB值&…...

涂鸦T5AI手搓语音、emoji、otto机器人从入门到实战
“🤖手搓TuyaAI语音指令 😍秒变表情包大师,让萌系Otto机器人🔥玩出智能新花样!开整!” 🤖 Otto机器人 → 直接点明主体 手搓TuyaAI语音 → 强调 自主编程/自定义 语音控制(TuyaAI…...
精益数据分析(97/126):邮件营销与用户参与度的关键指标优化指南
精益数据分析(97/126):邮件营销与用户参与度的关键指标优化指南 在数字化营销时代,邮件列表效度、用户参与度和网站性能等指标往往决定着创业公司的增长成败。今天,我们将深入解析邮件打开率、网站可用性、页面参与时…...

Mac下Android Studio扫描根目录卡死问题记录
环境信息 操作系统: macOS 15.5 (Apple M2芯片)Android Studio版本: Meerkat Feature Drop | 2024.3.2 Patch 1 (Build #AI-243.26053.27.2432.13536105, 2025年5月22日构建) 问题现象 在项目开发过程中,提示一个依赖外部头文件的cpp源文件需要同步,点…...

AI,如何重构理解、匹配与决策?
AI 时代,我们如何理解消费? 作者|王彬 封面|Unplash 人们通过信息理解世界。 曾几何时,PC 与移动互联网重塑了人们的购物路径:信息变得唾手可得,商品决策变得高度依赖内容。 但 AI 时代的来…...
【前端异常】JavaScript错误处理:分析 Uncaught (in promise) error
在前端开发中,JavaScript 异常是不可避免的。随着现代前端应用越来越多地使用异步操作(如 Promise、async/await 等),开发者常常会遇到 Uncaught (in promise) error 错误。这个错误是由于未正确处理 Promise 的拒绝(r…...

认识CMake并使用CMake构建自己的第一个项目
1.CMake的作用和优势 跨平台支持:CMake支持多种操作系统和编译器,使用同一份构建配置可以在不同的环境中使用 简化配置:通过CMakeLists.txt文件,用户可以定义项目结构、依赖项、编译选项等,无需手动编写复杂的构建脚本…...

[论文阅读]TrustRAG: Enhancing Robustness and Trustworthiness in RAG
TrustRAG: Enhancing Robustness and Trustworthiness in RAG [2501.00879] TrustRAG: Enhancing Robustness and Trustworthiness in Retrieval-Augmented Generation 代码:HuichiZhou/TrustRAG: Code for "TrustRAG: Enhancing Robustness and Trustworthin…...

Neko虚拟浏览器远程协作方案:Docker+内网穿透技术部署实践
前言:本文将向开发者介绍一款创新性协作工具——Neko虚拟浏览器。在数字化协作场景中,跨地域的团队常需面对实时共享屏幕、协同编辑文档等需求。通过本指南,你将掌握在Ubuntu系统中使用容器化技术部署该工具的具体方案,并结合内网…...