【问题标题】:What can happen if printf is called with a wrong format string?如果使用错误的格式字符串调用 printf 会发生什么?
【发布时间】:2013-01-24 14:52:47
【问题描述】:

或者换句话说:错误的printf/fprintf十进制整数(%d%u%ld%lld)格式字符串会导致程序崩溃或导致未定义的行为吗?

Cosinder 以下代码行:

#include <iostream>
#include <cstdio>

int main() {
    std::cout << sizeof(int) << std::endl
              << sizeof(long) << std::endl;

    long a = 10;
    long b = 20;
    std::printf("%d, %d\n", a, b);

    return 0;
}

32 位架构的结果:

4
4
10, 20

64 位架构的结果:

4
8
10, 20

在任何情况下,程序都会打印出预期的结果。我知道,如果long 的值超出int 的范围,程序会打印错误的数字——这很难看,但不会影响程序的主要目的——但除此之外,还会发生什么意外吗?

【问题讨论】:

标签: c++


【解决方案1】:

如果使用错误的格式字符串调用 printf 会发生什么?

任何事情都可能发生。这是未定义的行为!
未定义的行为意味着任何事情都可能发生。它可能会向您显示您期望的结果,也可能不会或可能会崩溃。任何事情都有可能发生,除了你自己,你不能责怪任何人。

参考:

c99 标准:7.19.6.1:
第 9 段:

如果转换规范无效,则行为未定义。225) 如果任何参数是 不是相应覆盖规范的正确类型,行为是 未定义。

【讨论】:

  • 你的意思是char c=1;printf("%d",c); 也是未定义的行为吗?
  • “你不能怪任何人,只能怪你自己”——最后我对此有一个很好的回应;见this blog post末尾的“责备程序员”。
  • @rondino 否,因为c 在传递给printf() 之前被提升为int,请参阅“默认参数提升”。
【解决方案2】:

这是未定义的行为 - 规范中没有任何内容告诉编译器设计者(或 C 库设计者)应该如何处理,因此他们可以做任何事情。

在实践中,这完全取决于对数字的解释,而且很可能,您不会从这样做中得到任何好处。真正糟糕的是当您将字符串与整数格式混合时 - 字符串将很好地打印为(可能是奇怪的)数字,但数字在作为字符串传递时不太可能“工作” - 因为字符串是指向第一个地址的指针字符 - 并且大多数数字在典型系统中都不是有效指针,因此它会崩溃。

但是没有任何保证。在您的 64 位示例中,很明显该数字是“小端”。用 0x100000000 尝试同样的事情,它会打印 0 - 因为其余的数字都丢失了。

【讨论】:

    【解决方案3】:

    哦,是的 - printf 取决于格式字符串来确定接下来要获取的变量的大小和类型。当格式字符串错误时,它可能会尝试获取甚至不存在的变量,并可能产生所有后果。

    【讨论】:

      【解决方案4】:

      如果使用错误的格式字符串调用 printf,任何事情都可能发生。它的未定义行为,永远不应该依赖未定义的行为。

      【讨论】:

        【解决方案5】:

        不要使用 printf

        printf 是 C 时代的遗物,不再需要...改用 std::cout 和 I/O 操纵器。

        【讨论】:

        • 这通常是一个合理的建议,但它没有回答问题。
        • @AlokSave 非常正确,但我认为 OP 提出了错误的问题。
        • 没有错题。有格式错误的问题和正确格式的问题。只需忽略 Q 上的 C++ 标签,这将成为一个完全有效的 Q。
        • 在我们的嵌入式代码中,我们使用 c++ 但不使用 iostreams,我们将 snprintf 和 vsnprintf 与自定义日志记录函数/方法结合使用。所以 printf 系列仍然非常相关和有用。另请注意,整个标准 c 库是旧 C 时代的“遗物”。它被广泛使用、维护,并且对世界各地的大量开发人员仍然有用。
        猜你喜欢
        • 2013-05-27
        • 1970-01-01
        • 2022-06-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多