首先先说解决方法:
在程序最顶端加入这个代码段
#define _CRT_SECURE_NO_WARNINGS
这主要是微软的 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
函数有三个参数,它们的含义分别是:
-
目标缓冲区:
fgets
函数将从输入流中读取的数据存储在目标缓冲区中。这是一个指向字符数组的指针,用于接收输入的字符串数据。 -
缓冲区大小:这个参数指定了目标缓冲区的大小(以字节数表示)。
fgets
函数将最多读取size-1
个字符到目标缓冲区中,这是为了为字符串终止符\0
预留空间。 -
输入流:这个参数指定了要从哪个输入流中读取数据。通常是标准输入流
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
函数有三个参数,它们的含义分别是:
-
目标字符串:这是一个指向字符数组的指针,用于存储复制后的字符串。
-
源字符串:这是一个指向字符数组的指针,表示要复制的原始字符串。
-
复制的字符数:这个参数表示要复制的字符数,即将源字符串中的多少个字符复制到目标字符串中。
#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
函数有三个参数,它们的含义分别是:
-
目标指针:这是一个指向目标内存区域的指针,用于存储复制后的数据。
-
源指针:这是一个指向源内存区域的指针,表示要复制的原始数据。
-
复制的字节数:这个参数表示要复制的字节数,即将源内存区域中的多少个字节复制到目标内存区域中。文章来源:https://www.toymoban.com/news/detail-549774.html
#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模板网!