首先先说解决方法:

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

#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函数有三个参数,它们的含义分别是:

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

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

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

#include int main() {char input[100]; // 假设缓冲区大小为 100printf("请输入字符串: ");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 #include 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 #include int main() {char source[10] = "Hello"; // 源内存char destination[20]; // 目标内存memcpy(destination, source, strlen(source) + 1); // 将 source 复制到 destinationprintf("目标内存中的内容是: %s\n", destination);return 0;}

在上面的示例中,`memcpy` 函数将源内存 `source` 复制到目标内存 `destination` 中,并且 `strlen(source) + 1` 是要复制的字节数,包括字符串结尾的空字符 ‘\0’。