scanf和strcpy这类关键字和函数为什么不安全,使用VS编译会报错

这篇具有很好参考价值的文章主要介绍了scanf和strcpy这类关键字和函数为什么不安全,使用VS编译会报错。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

首先先说解决方法:

在程序最顶端加入这个代码段

#define  _CRT_SECURE_NO_WARNINGS

这主要是微软的 C 运行时库实现将这些函数标记为不安全,主要原因是这些函数缺乏对输入长度的边界检查,容易导致缓冲区溢出漏洞。

会产生这样的报错:

scanf和strcpy这类关键字和函数为什么不安全,使用VS编译会报错,C语言,安全,c++

即:

C4996    'strcpy': This function or variable may be unsafe. Consider using strcpy_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details. 

下面是关于`scanf`和`strcpy`为什么可能不安全的一些主要原因:

1. 缓冲区溢出:`scanf`和`strcpy`函数不对输入进行边界检查,导致可能发生缓冲区溢出。这意味着当输入的字符串长度超过目标缓冲区的容量时,会覆盖相邻内存空间的数据。攻击者可以利用这种漏洞来执行恶意代码或者修改程序的行为。

2. 字符串终止符`\0`处理问题:`strcpy`函数在拷贝字符串时,需要确保目标缓冲区具有足够的空间来容纳源字符串,以及在目标缓冲区的末尾添加字符串终止符`\0`。如果源字符串比目标缓冲区大,或者忘记添加`\0`,会导致缓冲区溢出或未定义的行为。

3. 无法处理特殊字符:`scanf`函数对于输入中的特殊字符(例如空格、制表符等)的处理不够灵活。默认情况下,`scanf`会将这些特殊字符视为输入结束的标志,因此可能无法正确读取包含特殊字符的字符串。

4. 难以追踪和调试:由于不安全的函数和关键字使用不依赖于输入的长度,因此很难在运行时捕获和排查相关问题。这可能导致程序的脆弱性更加难以发现和修复。

为微软官方给出的建议是,可以考虑使用更安全的替代函数和关键字,如`fgets`、`strncpy`等,但是其实也并不见得安全,同样存在问题,需要结合适当的输入验证和边界检查来确保程序的安全性。

下面介绍一下这些替代的函数怎么用:

1. 使用 `fgets` 读取用户输入:

fgets 函数有三个参数,它们的含义分别是:

  1. 目标缓冲区:fgets 函数将从输入流中读取的数据存储在目标缓冲区中。这是一个指向字符数组的指针,用于接收输入的字符串数据。

  2. 缓冲区大小:这个参数指定了目标缓冲区的大小(以字节数表示)。fgets 函数将最多读取 size-1 个字符到目标缓冲区中,这是为了为字符串终止符 \0 预留空间。

  3. 输入流:这个参数指定了要从哪个输入流中读取数据。通常是标准输入流 stdin,表示从键盘读取用户输入。你也可以指定其他的输入流,如从文件中读取。

#include <stdio.h>

int main() {
    char input[100]; // 假设缓冲区大小为 100

    printf("请输入字符串: ");
    fgets(input, sizeof(input), stdin); // 从标准输入读取字符串,最多读取 sizeof(input)-1 个字符

    printf("输入的字符串是: %s\n", input);

    return 0;
}

`fgets` 函数读取一行输入,包括空格,将其存储在目标缓冲区 `input` 中(读取的最大字符数为 `sizeof(input)-1`)。`input` 的大小减去 1 是为了让函数有足够的空间在最后添加字符串终止符 '\0'。

2. 使用 `strncpy` 复制字符串到目标缓冲区:

strncpy 函数有三个参数,它们的含义分别是:

  1. 目标字符串:这是一个指向字符数组的指针,用于存储复制后的字符串。

  2. 源字符串:这是一个指向字符数组的指针,表示要复制的原始字符串。

  3. 复制的字符数:这个参数表示要复制的字符数,即将源字符串中的多少个字符复制到目标字符串中。

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

int main() {
    char source[10] = "Hello"; // 源字符串
    char destination[20]; // 目标缓冲区

    strncpy(destination, source, sizeof(destination)-1); // 复制 source 到 destination,最多复制 sizeof(destination)-1 个字符
    destination[sizeof(destination)-1] = '\0'; // 手动添加字符串终止符 '\0'

    printf("目标缓冲区中的字符串是: %s\n", destination);

    return 0;
}

`strncpy` 函数将源字符串 `source` 复制到目标缓冲区 `destination` 中,最多复制 `sizeof(destination)-1` 个字符。需要注意的是,`strncpy` 不会自动添加字符串终止符 '\0',因此需要手动在目标缓冲区末尾添加。

3.使用 `memcpy` 将一段内存的内容复制到另一段内存中的示例:

“Memory Copy”,即内存拷贝,memcpy 函数有三个参数,它们的含义分别是:

  1. 目标指针:这是一个指向目标内存区域的指针,用于存储复制后的数据。

  2. 源指针:这是一个指向源内存区域的指针,表示要复制的原始数据。

  3. 复制的字节数:这个参数表示要复制的字节数,即将源内存区域中的多少个字节复制到目标内存区域中。

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

int main() {
    char source[10] = "Hello"; // 源内存
    char destination[20]; // 目标内存

    memcpy(destination, source, strlen(source) + 1); // 将 source 复制到 destination

    printf("目标内存中的内容是: %s\n", destination);

    return 0;
}

在上面的示例中,`memcpy` 函数将源内存 `source` 复制到目标内存 `destination` 中,并且 `strlen(source) + 1` 是要复制的字节数,包括字符串结尾的空字符 '\0'。文章来源地址https://www.toymoban.com/news/detail-549774.html

到了这里,关于scanf和strcpy这类关键字和函数为什么不安全,使用VS编译会报错的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【C++入门】引用、内联函数、auto 关键字

    从语法上理解,引用就是给变量取一个 别名 ,它没有独立空间,和它引用的变量共用一块空间。 例子: 值得注意的是,C++ 中的引用一经初始化,后面是改变不了指向的(这点与Java有所不同),而且引用是必须初始化的。 引用的类型也必须和原变量对应,显然,你肯定不能

    2024年02月16日
    浏览(34)
  • 【C++】引用、内联函数、auto关键字等

    前言:在前面我们讲解了C++入门基础的一些学习例如命名空间、缺省参数、函数重载等。今天我们将进一步的学习,跟着博主的脚步再次往前迈一步吧。 💖 博主CSDN主页:卫卫卫的个人主页 💞 👉 专栏分类:高质量C++学习 👈 💯代码仓库:卫卫周大胖的学习日记💫 💪关注博

    2024年02月20日
    浏览(37)
  • 【C++初阶(三)】引用&内联函数&auto关键字

    目录  前言  1. 引用   1.1 引用的概念   1.2 引用的特性  1.3 引用的权限  1.4 引用的使用  1.5 引用与指针的区别 2. 内联函数 2.1  什么是内联函数 2.2  内联函数的特性  3. auto  3.1 auto简介  3.2 auto使用规则  3.3 auto不能使用的场景 4.  基于范围的for循环  4.1 范围for使用

    2024年02月08日
    浏览(42)
  • 【SQL】SQL的基础知识-语法、关键字、函数

    SQL(Structured Query Language)是一种用于管理关系数据库管理系统(RDBMS)的语言。在本文中,我们将讨论SQL的基础知识,包括语法、和函数。 SQL语法由多个和操作符组成,用于完成对数据的操作。以下是SQL的基础语法: 其中, SELECT 用于选择要查询的列,

    2024年02月06日
    浏览(37)
  • 【C++初阶】关键字&命名空间&缺省函数&函数重载入门必看!!!超详解!!!

     ========================================================================= 主页点击直达: 个人主页 我的小仓库:代码仓库 C语言偷着笑: C语言专栏 数据结构挨打小记: 初阶数据结构专栏 Linux被操作记:Linux专栏 LeetCode刷题掉发记: LeetCode刷题 算法: 算法专栏  C++头疼记: C++专栏 计算机

    2024年02月07日
    浏览(34)
  • 【C++】const、static关键字和构造函数初始化

    💗个人主页💗 ⭐个人专栏——C++学习⭐ 💫点击关注🤩一起学习C语言💯💫 目录 1. const修饰成员函数 1.1 语法格式 1.2 权限放大缩小 1.3 思考 1.4 解答 2. 再谈构造函数 2.1 构造函数体赋值 2.2 初始化列表 2.3 explicit 3. static成员 3.1 静态变量 3.2 静态函数 3.3 静态成员变量

    2024年02月19日
    浏览(34)
  • 【Python】函数进阶 ① ( 函数返回多个返回值 | 函数参数传递类型简介 | 位置参数 | 关键字参数 )

    在函数中 , 如果要 返回 多个返回值 , 可以 在 return 语句中 , 设置多个返回值 , 这些返回值之间使用 逗号 隔开 , 这些返回值的类型是 元组 tuple 类型的 ; 在下面的代码中 , 返回了 3 个返回值 , 其 本质上是返回了一个包含 3 个元素的 元组 数据容器 , 可以使用多重赋值将返回的

    2024年02月11日
    浏览(37)
  • 【JavaScript】函数 ④ ( 函数返回值 | 函数返回值语法 return 关键字 | 函数默认返回值 undefined )

    JavaScript 函数 可以 实现某种特定的功能 , 执行完毕后 , 可以返回一个 \\\" 返回值 \\\" ; 当 函数 被调用执行任务完毕时 , \\\" 返回值 \\\" 会被返回给调用者 ; 如果 函数 中没有明确 使用 return 返回 \\\" 返回值 \\\" , 那么函数会默认返回undefined 值 ; 在 JavaScript 中 , 函数 返回值是 通过

    2024年04月10日
    浏览(40)
  • 【C++初阶】引用&内联函数&auto关键字&范围for循环&nullptr

    ========================================================================= 个人主页还有更多系列专栏: 小白不是程序媛 我的小仓库: Gitee C++系列专栏: C++头疼记 ========================================================================= 目录 前言 引用 概念 引用的特点 常引用  引用的使用场景 做参数  做返

    2024年02月08日
    浏览(33)
  • 【C++】C++入门第二课(函数重载 | 引用 | 内联函数 | auto关键字 | 指针空值nullptr)

    目录 前言 函数重载 概念 重载函数的条件 C++支持重载函数的原理--名字修饰 引用 概念 特性 常引用(const引用) 使用场景 传值,传引用效率比较 引用和指针的区别 内联函数 概念 特性 auto(C++11) auto简介 auto的使用规则 指针空值nullptr(C++11) C++98中的指针空值 结语

    2024年04月15日
    浏览(34)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包