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

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

首先先说解决方法:

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

#define  _CRT_SECURE_NO_WARNINGS

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

会产生这样的报错:

strcpy安全问题,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-629568.html

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

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

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

相关文章

  • 【C++】:函数重载,引用,内联函数,auto关键字,基于范围的for循环,nullptr关键字

    在C语言中,同名函数是不能出现在同一作用域的,但是在C++中却可以,但是要满足函数重载的规则。 那什么是函数重载呢?它的规则是什么呢? 函数重载 :是函数的一种特殊情况,C++允许在 同一作用域 中声明几个功能类似的 同名函数 ,这些同名函数的 形参列表(参数个数

    2024年04月26日
    浏览(44)
  • 【C++】关键字 & 命名空间 & 输入输出 & 缺省函数

    C++  总计 63 个, C语言 32 个 直接上图:  asm do if return try continue auto double inline short typedef for bool dynamic_cast int signed typeid public break else long sizeof typename throw case enum mutable static union wchar_t catch explicit namespace static_cast unsigned default char export new struct using friend class ext

    2024年02月08日
    浏览(39)
  • 【C++入门】引用、内联函数、auto 关键字

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

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

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

    2024年02月20日
    浏览(45)
  • C语言volatile关键字

    在C语言中, volatile 是一个类型修饰符,用于告诉编译器对象的值可能会在编译器无法检测到的情况下被改变。这通常发生在以下两种情况: 硬件的输入/输出操作,例如一个设备寄存器的读取或写入。 共享内存的并行程序,其中一个线程修改了一个内存位置,而另一个线程

    2024年02月07日
    浏览(44)
  • 【C语言】for 关键字

    🚩WRITE IN FRONT🚩    🔎介绍:\\\"謓泽\\\"正在路上朝着\\\"攻城狮\\\"方向\\\"前进四\\\"🔎 🏅荣誉:2021|2022年度博客之星物联网与嵌入式开发TOP5|TOP4、2021|2022博客之星TOP100|TOP63、阿里云专家博主、掘金优秀创作者、全网粉丝量5w+、全网访问量70w+🏅 🆔本文章内容由 謓泽 原创 如需相关转载

    2023年04月17日
    浏览(26)
  • 【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日
    浏览(51)
  • 【C语言】static关键字详解

    目录 1.static是什么? 2.static修饰的对象是? 3.static修饰后改变了什么? 4.static修饰操作演示 (1) 局部变量 如果加了static修饰局部变量i会怎么样? 全局区(静态区) (2) 全局变量 如果给全局变量加上了static修饰呢? 二者区别?  这样用有什么用? (3) 函数 5.总结

    2024年02月10日
    浏览(37)
  • C语言-外部关键字extern

    extern  extern 用在全局变量或函数的声明前,用来说明“此变量/函数是在别处定义的,要在此处引用。  什么是定义,什么是声明?       什么是定义:所谓的定义就是为这个变量分配一块内存并给它取上一个名字,这个名字就是我们经常所说的变量名。但注意,这个名

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

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

    2024年02月06日
    浏览(46)

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

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

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

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

二维码1

领取红包

二维码2

领红包