32. C 语言 安全函数( _s 尾缀)

news2025/2/3 2:11:24

本章目录

    • 前言
    • 什么是安全函数?
      • 安全函数的特点
      • 主要的安全函数
        • 1. 字符串操作安全函数
        • 2. 格式化输出安全函数
        • 3. 内存操作安全函数
        • 4. 其他常用安全函数
    • 安全函数实例
      • 示例 1:`strcpy_s` 和 `strcat_s`
      • 示例 2:`memcpy_s`
      • 示例 3:`strtok_s`
    • 总结


前言

在 C 语言的编程中,缓冲区溢出是常见的安全问题之一。它发生在程序尝试将数据写入一个不足够大的缓冲区时,导致数据覆盖了相邻内存区域。这种错误不仅会导致程序崩溃,还可能导致潜在的安全漏洞,使攻击者能够通过精心设计的输入数据控制程序流,甚至执行恶意代码。

为了避免这类问题,C11 标准引入了一些 “安全函数”(通常称为 Annex K 函数),这些函数是传统 C 函数的增强版本,增加了缓冲区大小检查和错误处理机制,从而提升了程序的安全性。

本文将带您深入了解 C 语言中的安全函数,帮助您编写更加健壮和安全的代码。


什么是安全函数?

在 C 语言中,安全函数是指那些在执行字符串和内存操作时,显式检查目标缓冲区大小并报告错误的函数。它们的设计初衷是防止缓冲区溢出、访问越界等问题。安全函数通常返回一个 errno_t 类型的错误码,以便调用者能够检测是否成功执行。

安全函数的特点

  1. 缓冲区大小检查:安全函数需要明确传递目标缓冲区的大小,确保不会发生溢出。
  2. 返回值检查:大多数安全函数返回一个错误代码,可以通过检查返回值来判断是否成功执行。
  3. 错误处理:当缓冲区大小不足或者其他错误发生时,安全函数会尝试清空或初始化输出缓冲区,避免未定义的行为。

主要的安全函数

以下是 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_sstrcat_s

#include <stdio.h>
#include <string.h>

int main() {
    char dest[20]; // 目标缓冲区大小为 20
    const char *src = "Hello, World!";

    // 使用 strcpy_s 将 src 复制到 dest
    if (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" 追加到 dest
    const 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 将数据复制到 dest
    if (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 语言中的安全函数是为了提高代码的安全性而设计的,尤其是在防止缓冲区溢出、内存越界等常见错误方面提供了有效的防护。通过使用这些函数,您可以确保程序在处理字符串和内


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

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

相关文章

ArkTS编程规范

文章目录 目标和适用范围规则来源章节概览代码风格编程实践 术语和定义总体原则命名类名、枚举名、命名空间名采用UpperCamelCase风格变量名、方法名、参数名采用lowerCamelCase风格常量名、枚举值名采用全部大写&#xff0c;单词间使用下划线隔开避免使用否定的布尔变量名&…

深度学习之“向量范数和距离度量”

在深度学习中&#xff0c;范数和向量距离是两个不同的概念。向量范数是一种函数&#xff0c;用于将一个实数或复数向量映射为一个值。虽然范数通常用于度量向量之间的距离&#xff0c;但是同样也有其它的一些表示距离的方式。 范数距离 范数是具有“长度”概念的函数。在向量…

基于Python的简单企业维修管理系统的设计与实现

以下是一个基于Python的简单企业维修管理系统的设计与实现&#xff0c;这里我们会使用Flask作为Web框架&#xff0c;SQLite作为数据库来存储相关信息。 1. 需求分析 企业维修管理系统主要功能包括&#xff1a; 维修工单的创建、查询、更新和删除。设备信息的管理。维修人员…

< OS 有关 > Android 手机 SSH 客户端 app: connectBot

connectBot 开源且功能齐全的SSH客户端,界面简洁,支持证书密钥。 下载量超 500万 方便在 Android 手机上&#xff0c;连接 SSH 服务器&#xff0c;去运行命令。 Fail2ban 12小时内抓获的 IP ~ ~ ~ ~ rootjpn:~# sudo fail2ban-client status sshd Status for the jail: sshd …

【算法设计与分析】实验7:复杂装载及0/1背包问题的回溯法设计与求解

目录 一、实验目的 二、实验环境 三、实验内容 四、核心代码 五、记录与处理 六、思考与总结 七、完整报告和成果文件提取链接 一、实验目的 针对复杂装载问题、及0/1背包问题开展分析、建模、评价&#xff0c;算法设计与优化&#xff0c;并进行编码实践。 理解复杂装载…

仿真设计|基于51单片机的温湿度、一氧化碳、甲醛检测报警系统

目录 具体实现功能 设计介绍 51单片机简介 资料内容 仿真实现&#xff08;protues8.7&#xff09; 程序&#xff08;Keil5&#xff09; 全部内容 资料获取 具体实现功能 &#xff08;1&#xff09;温湿度传感器、CO传感器、甲醛传感器实时检测温湿度值、CO值和甲醛值进…

使用vhd虚拟磁盘安装两个win10系统

使用vhd虚拟磁盘安装两个win10系统 前言vhd虚拟磁盘技术简介准备工具开始动手实践1.winX选择磁盘管理2.选择“操作”--“创建VHD”3.自定义一个位置&#xff0c;输入虚拟磁盘大小4.右键初始化磁盘5.选择GPT分区表格式6.右键新建简单卷7.给卷起个名字&#xff0c;用于区分8.打开…

深入理解Spring事务管理

一、事务基础概念 1.1 什么是事务&#xff1f; 事务&#xff08;Transaction&#xff09;是数据库操作的最小工作单元&#xff0c;具有ACID四大特性&#xff1a; 原子性&#xff08;Atomicity&#xff09;&#xff1a;事务中的操作要么全部成功&#xff0c;要么全部失败 一致…

自制虚拟机(C/C++)(二、分析引导扇区,虚拟机读二进制文件img软盘)

先修复上一次的bug&#xff0c;添加新指令&#xff0c;并增加图形界面 #include <graphics.h> #include <conio.h> #include <windows.h> #include <commdlg.h> #include <iostream> #include <fstream> #include <sstream> #inclu…

ASP.NET Core 启动并提供静态文件

ASP.NET Core 启动并提供静态文件 即是单个可执行文件&#xff0c;它既运行 API 项目&#xff0c;也托管 前端项目&#xff08;通常是前端的发布文件&#xff09;。 这种方式一般是通过将 前端项目 的发布文件&#xff08;例如 HTML、CSS、JavaScript&#xff09;放入 Web AP…

4 [危机13小时追踪一场GitHub投毒事件]

事件概要 自北京时间 2024.12.4 晚间6点起&#xff0c; GitHub 上不断出现“幽灵仓库”&#xff0c;仓库中没有任何代码&#xff0c;只有诱导性的病毒文件。当天&#xff0c;他们成为了 GitHub 上 star 增速最快的仓库。超过 180 个虚假僵尸账户正在传播病毒&#xff0c;等待不…

变量和常量

一.变量 1.标准声明 var 变量名 变量类型 变量声明行末不需要分号 2..批量声明 package main import "fmt" func main(){var(a string b int c boold float32)}3.变量的初始化 var a int 10 var b float321.1 4.类型推导 var name"tom" var age18 fmt.Pr…

大模型概述(方便不懂技术的人入门)

1 大模型的价值 LLM模型对人类的作用&#xff0c;就是一个百科全书级的助手。有多么地百科全书&#xff0c;则用参数的量来描述&#xff0c; 一般地&#xff0c;大模型的参数越多&#xff0c;则该模型越好。例如&#xff0c;GPT-3有1750亿个参数&#xff0c;GPT-4可能有超过1万…

流浪 Linux: 外置 USB SSD 安装 ArchLinux

注: ArchLinux 系统为滚动更新, 变化很快, 所以本文中的安装方法可能很快就过时了, 仅供参考. 实际安装时建议去阅读官方文档. 最近, 突然 (也没有那么突然) 有了一大堆 PC: 4 个笔记本, 2 个台式主机 (M-ATX 主板), 1 个小主机 (迷你主机). 嗯, 多到用不过来. 但是, 窝又不能…

Hot100之子串

560和为K的子数组 题目 给你一个整数数组 nums 和一个整数 k &#xff0c;请你统计并返回 该数组中和为 k 的子数组的个数 。 子数组是数组中元素的连续非空序列 思路解析 ps&#xff1a;我们的presum【0】就是0&#xff0c;如果没有这个0的话我们的第一个元素就无法减去上…

网络工程师 (11)软件生命周期与开发模型

一、软件生命周期 前言 软件生命周期&#xff0c;也称为软件开发周期或软件开发生命周期&#xff0c;是指从软件项目的启动到软件不再被使用为止的整个期间。这个过程可以细分为多个阶段&#xff0c;每个阶段都有其特定的目标、任务和产出物。 1. 问题定义与需求分析 问题定义…

(三)QT——信号与槽机制——计数器程序

目录 前言 信号&#xff08;Signal&#xff09;与槽&#xff08;Slot&#xff09;的定义 一、系统自带的信号和槽 二、自定义信号和槽 三、信号和槽的扩展 四、Lambda 表达式 总结 前言 信号与槽机制是 Qt 中的一种重要的通信机制&#xff0c;用于不同对象之间的事件响…

hot100_21. 合并两个有序链表

将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。 示例 1&#xff1a; 输入&#xff1a;l1 [1,2,4], l2 [1,3,4] 输出&#xff1a;[1,1,2,3,4,4] 示例 2&#xff1a; 输入&#xff1a;l1 [], l2 [] 输出&#xff1a;[…

安全防护前置

就业概述 网络安全工程师/安全运维工程师/安全工程师 安全架构师/安全专员/研究院&#xff08;数学要好&#xff09; 厂商工程师&#xff08;售前/售后&#xff09; 系统集成工程师&#xff08;所有计算机知识都要会一点&#xff09; 学习目标 前言 网络安全事件 蠕虫病毒--&…

01-六自由度串联机械臂(ABB)位置分析

ABB工业机器人&#xff08;IRB2600&#xff09;如下图所示&#xff08;d1444.8mm&#xff0c;a1150mm&#xff0c;a2700mm&#xff0c;a3115mm&#xff0c;d4795mm&#xff0c;d685mm&#xff09;&#xff0c;利用改进DH法建模&#xff0c;坐标系如下所示&#xff1a; 利用改进…