【问题标题】:Scanf read string over size of predefined char arrayScanf 读取超过预定义字符数组大小的字符串
【发布时间】:2019-01-26 04:03:51
【问题描述】:

我正在尝试通过scanf 读取字符串,如下所示:

char input[8];
scanf("%s",input);

事实证明,该程序可以读取超过 8 个字符。假设我输入了 123456789012345,strlen(input) 返回 15。

但是当我将输入设置为:

char input[4];
scanf("%s",input);

输入“12345”会导致“16146 分段错误”。 有谁知道这是怎么回事?

【问题讨论】:

  • 发生这种情况是因为您没有像应有的那样分别使用"%7s""%3s"
  • 当输入的字符串长于存储它的可用空间时,您会遇到“未定义的行为”。任何事情都有可能发生。这包括崩溃并似乎可以工作,以及重新格式化您的磁盘驱动器。见How to prevent scanf() causing a buffer overflow?
  • 您正在调用undefined behavior。这意味着从字面上看,任何事情都可能发生,包括崩溃,甚至时间旅行(是的,真的)。未定义的行为还包括您的程序看起来“工作正常”,但实际上,您只是走运了,当您进行通常不应该影响程序行为的最小更改时,您的程序可能会有不同的行为。仅仅因为你的程序看起来可以工作并不意味着它是格式良好的,并且当你编写一个格式不正确的程序时,也不能保证你会得到一个错误。

标签: c string char scanf


【解决方案1】:

从技术上讲,这两种情况都会调用未定义的行为。第一种情况恰好在您的系统上工作不应该被认为意味着您的程序是定义良好的。测试只能表明错误的存在,而不是它们的缺失。

由于您仍在学习 CI 将借此机会为您提供有关读取来自 stdin 的输入的建议:始终将要读取的输入长度限制为正在读取的缓冲区的长度,保留一个在结尾处为空终止符。

如果您想使用scanfstdin 读取字符串,那么在字符串格式说明符前面加上字符串的最大长度比使用原始"%s" 更安全。例如,如果我有一个char buffer[20]; 是调用scanf 的目的地,我将使用格式字符串"%19s"

【讨论】:

    【解决方案2】:

    两者都是所谓的未定义行为,应该不惜一切代价避免。没有比由此引起的错误更难找到了。

    那么为什么会这样呢?嗯,这就是未定义行为的问题。它可能会起作用。你根本没有任何保证。

    在此处阅读有关 UB 的更多信息:Undefined, unspecified and implementation-defined behavior

    【讨论】:

      猜你喜欢
      • 2012-08-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多