【问题标题】:printf insufficient argumentsprintf 参数不足
【发布时间】:2012-09-30 09:39:04
【问题描述】:

我的问题是关于缺少参数的 printf 之后的行为:

printf("%s blah blah %d", int); // integer was given as argument (and not int written)

我已经知道,如果格式的参数不足,则行为是 未定义。

问题是对于 printf 结果还是对于整个程序是未定义的?

  • 当 %s 尝试从未经授权的内存地址读取时,可能会发生崩溃。 (发生在我身上)
  • printf 完成后 [long] 是否会发生崩溃? (打印一些垃圾字符串和一个整数)

编辑:

为了澄清我不是在询问编译错误或警告,执行此行时程序也不会崩溃。问题是这行代码执行完后,程序会不会随机崩溃。

【问题讨论】:

  • 未定义的行为可以追溯。未定义行为之前的执行跟踪部分也可能会被搞砸。
  • 你的代码sn-p是语法错误; int 是一个类型,不是一个有效的参数。
  • 我写了 int 因为它是一个作为参数而不是字符串指针 (char*) 的 int 变量。

标签: c printf


【解决方案1】:

整个程序都没有定义。

事实上,在程序存在之前它是未定义的:编译器本身在文本printf("%s blah blah %d", int);存在时所做的事情是未定义的

【讨论】:

  • 除非编译器必须诊断语法错误(这可能是 OP 无意的)。
  • 很明显,OP 在询问该参数是否为 int,而不是 int 关键字。
【解决方案2】:

基本上适用于整个程序。 Printf 开始从堆栈中取出参数,在这种情况下,使用了一个价值太多的int。这通常类似于退货地址。因此,当 printf 返回时,它会返回堆栈中的下一个随机数。通常的结果(如果幸运的话)是分段错误。

因为它将参数压入堆栈,然后将它们弹出,所以它首先尝试获取int

如果您走运,它会找到一段可寻址的代码。这导致您的第二种情况,其中地址成为该随机字符散列的地址。现在它将尝试打印一个字符串,直到找到一个随机的 NUL 字符。

更新

正如 Joachim 所指出的,它的细节是由调用约定决定的,所以让我们做一个明确的例子。当调用 printf 函数时,返回地址要么被先推送,要么最后被推送。我们假设它首先被推送(在通常的架构上更常见),所以这个调用将需要 PUSH 返回地址、格式字符串的 PUSH 地址、一个 int 值——比如说 42。这给了我们这个堆栈:

RTN ADDR
ADDR OF STRING
42

并让堆栈指针 SP 指向堆栈上的下一个位置。

现在 printf 开始解释字符串。它查找int 参数的地址,并确定它是SP-1。所以字符串参数的地址必须是SP-2 ...但这是格式字符串的地址,因为没有字符串参数。然后它在寻找格式字符串的地址时,它想找到SP-3,但那是返回地址,一个可执行代码的地址。在大多数机器上,这应该会导致分段错误。

如果您查看调用约定的其他选项,您会发现它们中的每一个都查看了一些错误的东西,因为无论如何,printf 认为它需要引用三件事堆栈,而不是它拥有的两个。

【讨论】:

  • 嗯...我不确定我是否理解正确,但是使用例如cdecl 调用约定,它是推送和弹出参数的调用者(然后调用所以返回地址总是最后推送的),所以你不应该得到不匹配并返回错误的地址。我是不是误读了你的意思?
  • 约阿希姆,见上面的更新。真正的要点是调用约定可能会确定 what 使用了错误的东西,但它会 总是 是错误的,因为 printf 将 总是 正在寻找当只提供两件时,三件。
  • C 标准不需要实现来使用堆栈,并且现代 ABI 不必将至少第一个参数放在堆栈上,即使有一个参数(例如 x64、AAPCS),它是UB,没有别的。
  • @Olaf 直接阅读您上面的评论。 真正的问题是调用约定可能决定使用什么错误的东西,但它总是错误的,因为当只提供了两个东西时 printf 总是会寻找三个东西 然后注意答案是四年老的。如果您想添加其他答案,请执行。
  • @CharlieMartin 我确实注意到了两人的年龄,问答环节。我们刚刚关闭了最近的 dup(这就是我注意到这一点的原因),所以我试图帮助纠正它,一个新的答案没有多大意义,正是 因为的年龄。
猜你喜欢
  • 2017-06-26
  • 1970-01-01
  • 2017-10-04
  • 1970-01-01
  • 2017-05-24
  • 1970-01-01
  • 1970-01-01
  • 2012-02-14
  • 1970-01-01
相关资源
最近更新 更多