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文档,并提取里面的所有图片时发现会出现一摸一样的图片只解析一次,导致图片丢失,数量不对的情况。 …...
Docker 运行 Kafka 带 SASL 认证教程
Docker 运行 Kafka 带 SASL 认证教程 Docker 运行 Kafka 带 SASL 认证教程一、说明二、环境准备三、编写 Docker Compose 和 jaas文件docker-compose.yml代码说明:server_jaas.conf 四、启动服务五、验证服务六、连接kafka服务七、总结 Docker 运行 Kafka 带 SASL 认…...
Psychopy音频的使用
Psychopy音频的使用 本文主要解决以下问题: 指定音频引擎与设备;播放音频文件 本文所使用的环境: Python3.10 numpy2.2.6 psychopy2025.1.1 psychtoolbox3.0.19.14 一、音频配置 Psychopy文档链接为Sound - for audio playback — Psy…...
Robots.txt 文件
什么是robots.txt? robots.txt 是一个位于网站根目录下的文本文件(如:https://example.com/robots.txt),它用于指导网络爬虫(如搜索引擎的蜘蛛程序)如何抓取该网站的内容。这个文件遵循 Robots…...
Spring AI 入门:Java 开发者的生成式 AI 实践之路
一、Spring AI 简介 在人工智能技术快速迭代的今天,Spring AI 作为 Spring 生态系统的新生力量,正在成为 Java 开发者拥抱生成式 AI 的最佳选择。该框架通过模块化设计实现了与主流 AI 服务(如 OpenAI、Anthropic)的无缝对接&…...
Redis数据倾斜问题解决
Redis 数据倾斜问题解析与解决方案 什么是 Redis 数据倾斜 Redis 数据倾斜指的是在 Redis 集群中,部分节点存储的数据量或访问量远高于其他节点,导致这些节点负载过高,影响整体性能。 数据倾斜的主要表现 部分节点内存使用率远高于其他节…...
动态 Web 开发技术入门篇
一、HTTP 协议核心 1.1 HTTP 基础 协议全称 :HyperText Transfer Protocol(超文本传输协议) 默认端口 :HTTP 使用 80 端口,HTTPS 使用 443 端口。 请求方法 : GET :用于获取资源,…...
Selenium常用函数介绍
目录 一,元素定位 1.1 cssSeector 1.2 xpath 二,操作测试对象 三,窗口 3.1 案例 3.2 窗口切换 3.3 窗口大小 3.4 屏幕截图 3.5 关闭窗口 四,弹窗 五,等待 六,导航 七,文件上传 …...
Webpack性能优化:构建速度与体积优化策略
一、构建速度优化 1、升级Webpack和Node.js 优化效果:Webpack 4比Webpack 3构建时间降低60%-98%。原因: V8引擎优化(for of替代forEach、Map/Set替代Object)。默认使用更快的md4哈希算法。AST直接从Loa…...
代码规范和架构【立芯理论一】(2025.06.08)
1、代码规范的目标 代码简洁精炼、美观,可持续性好高效率高复用,可移植性好高内聚,低耦合没有冗余规范性,代码有规可循,可以看出自己当时的思考过程特殊排版,特殊语法,特殊指令,必须…...
android RelativeLayout布局
<?xml version"1.0" encoding"utf-8"?> <RelativeLayout xmlns:android"http://schemas.android.com/apk/res/android"android:layout_width"match_parent"android:layout_height"match_parent"android:gravity&…...
