解决VS'scanf':this function or variable may be unsafe.`(VS安全函数问题)

在 VS(Visual Studio)下编译C语言程序,如果使用了 scanf()、gets()、strcpy()、strcat() 等与字符串读取或操作有关的函数,有时候VS会报错,提示该函数可能不安全,并且建议替换为带有_s后缀的安全函数,如下图所示:

什么是安全函数(safe function)

scanf()、gets()、fgets()、strcpy()、strcat() 等都是C语言自带的函数,它们都是标准函数,但是它们都有一个缺陷,就是不安全,可能会导致数组溢出或者缓冲区溢出,让黑客有可乘之机,从而发起“缓冲区溢出”攻击。

scanf_s()、gets_s()、fgets_s()、strcpy_s()、strcat_s() 是微软自己发明的安全函数,它们仅适用于 VS,在其它编译器下无效。这些安全函数在读取或操作字符串时要求指明长度,这样一来,过多的字符就会被过滤掉,避免了数组或者缓冲区溢出。

下面我们以 scanf_s() 为例来讲解。

scanf() 在读取字符串时不会检查字符个数,它不知道数组或缓冲区到底能容纳多少个字符,例如:

 
  1. char buf[5]={0};
  2. scanf(“%s”, buf);

当用户输入abcdeABCDE这10个字符时,scanf() 会全部读取,并放入 buf 中,不过 buf 最多只能存储 5 个字符,不足以容纳用户输入的全部数据,所以多出来的 5 个字符就会使用 buf 后面的内存,而 buf 后面的内存可能没有使用权限,或者已经被别的数据占用,这就导致程序在运行时可能会出现不可预知的错误。

最要命的是,这种错误只能等到程序运行时才能检测出来,在编译期间根本无法检测;一旦检测出来只有一种后果,就是程序被操作系统终止,也就是我们常说的“程序崩溃”。

更改上面的代码,使用 scanf_s() 代替 scanf():

 
  1. char buf[5] = {0};
  2. scanf_s(“%s”, buf, 5);

scanf_s() 最后一个参数用来指明数组或者缓冲区的大小,假设它的值为 n,那么最多只允许读取 n-1 个字符(因为最后要存储'\0'),多出来的字符就不再读取了,这样就可以避免读入过多的字符。与 scanf() 相比,scanf_s() 显然更加安全。

但是,安全函数不利于大家学习,它们不但使用麻烦,而且也不被绝大多数教程采用。另外,安全函数是微软自己发明的,只适用于 VS 编译器,在其他编译器下无效。

如何取消安全函数的限制

我们通过对 VS 做适当的设置,让它不再强制使用安全函数,从而可以使用 scanf()、gets()、fgets()、strcpy()、strcat() 等C语言的标准函数去编程。

VS 之所以会提示使用安全函数,是因为它进行了SDL检查(安全性开发生命周期检查),只要将它取消就可以了。

1) 菜单栏中选择 “项目 --> xxx属性”(xxx为创建的项目名称),或者直接按下组合键“Alt+F7”,如下图所示:

2) 此时会弹出如下图所示的一个对话框,选择“C/C++ --> SDL检查”,将“是”改为“否”,如下图所示:

3、最后点击“确定”按钮,重新运行程序,你会发现程序可以正常运行了。

另外,VS2010、VS2015 等低版本的 VS 可以在创建项目之处就取消 SDL 检查(如下图所示),但是到了 VS2017 时就不行了,创建项目时没有这个选项了,只能在创建项目完成以后再按照以上步骤取消 SDL 检查。

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

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

相关文章

双向循环链表【数据结构】

单链表的缺点以及对单链表缺点的改进和双向链表的理解操作 双向循环列表的插入操作 线性结构是一种逻辑结构,顺序存储结构,链式存储结构

什么是编译器?(程序是怎么跑起来的)

我们平时所说的程序,是指双击后就可以直接运行的程序,这样的程序被称为可执行程序(Executable Program)。在 Windows 下,可执行程序的后缀有 .exe 和 .com(其中 .exe 比较常见);在类…

C++std命名空间和头文件详解

一个中大型软件往往由多名程序员共同开发,会使用大量的变量和函数,不可避免地会出现变量或函数的命名冲突。当所有人的代码都测试通过,没有问题时,将它们结合到一起就有可能会出现命名冲突。 例如小李和小韩都参与了一个文件管理系…

C++ new和delete

在C语言中,动态分配内存用 malloc() 函数,释放内存用 free() 函数。如下所示: int *p (int*) malloc( sizeof(int) * 10 ); //分配10个int型的内存空间free(p); //释放内存 在cpp中,这两个函数仍然可以使用,但是C又…

Java 的内存管理机制是怎样的?

Java 的内存管理机制是怎样的?

leetcode1103. 分糖果 II 该模拟就模拟,别老想着优化

排排坐,分糖果。 我们买了一些糖果 candies,打算把它们分给排好队的 n num_people 个小朋友。 给第一个小朋友 1 颗糖果,第二个小朋友 2 颗,依此类推,直到给最后一个小朋友 n 颗糖果。 然后,我们再回到…

leetcode912. 排序数组 有范围的排序统统用桶排序

给你一个整数数组 nums&#xff0c;请你将该数组升序排列。 示例 1&#xff1a; 输入&#xff1a;nums [5,2,3,1] 输出&#xff1a;[1,2,3,5] 示例 2&#xff1a; 输入&#xff1a;nums [5,1,1,2,0,0] 输出&#xff1a;[0,0,1,1,2,5] 提示&#xff1a; 1 < nums.len…

队列【数据结构】

注意 我们的销毁队列是否能够成功取决申请空间的方式&#xff0c;动态申请出来的空间都是可以进行销毁的&#xff0c;对于静态的话是不能直接进行销毁的 ADT 相当于是c当中的类结构&#xff0c;是处理数据时&#xff0c;提前对数据进行一定的管理操作&#xff0c;就是将某一件事…

C++继承详解

废话不多说直接上代码 class 派生类名:&#xff3b;继承方式&#xff3d; 基类名{ 派生类新增加的成员 }; 继承方式限定了基类成员在派生类中的访问权限&#xff0c;包括 public&#xff08;公有的&#xff09;、private&#xff08;私有的&#xff09;和 protected&…

串【数据结构F】

先来讲解一下串结构的概念性质的东西&#xff0c;以及我们需要注意的一些问题 串结构简单的ADT以及一些基本的操作 最小操作函数&#xff1a;就是功能已经达到了最小的功能实现了&#xff0c;不能继续执行更大的功能&#xff0c;类似于我们在家盖房子一样&#xff0c;水泥的…

C++ STL与迭代器

将容器类模板实例化时&#xff0c;会指明容器中存放的元素是什么类型的&#xff1a;可以存放基本类型的变量&#xff0c;也可以存放对象。 对象或基本类型的变量被插入容器中时&#xff0c;实际插入的是对象或变量的一个复制品。 STL 中的许多算法&#xff08;即函数模板&…

在JSP页面中输出JSON格式数据

JSON-taglib是一套使在JSP页面中输出JSON格式数据的标签库。 JSON-taglib主页&#xff1a; http://json-taglib.sourceforge.net/index.html JAR包下载地址&#xff1a; http://sourceforge.net/projects/json-taglib/files/latest/download 使用方法&#xff1a; 1、下载js…

git/github使用完整教程(1)基础

安装git 在Linux上安装Git 首先输入git&#xff0c;看看系统有没有安装Git&#xff1a; $ git The program git is currently not installed. You can install it by typing: sudo apt-get install git像上面的命令&#xff0c;有很多Linux会友好地告诉你Git没有安装&#x…