代码之家  ›  专栏  ›  技术社区  ›  JSBÕ±Õ¸Õ£Õ¹

向printf传递的参数太多

  •  29
  • JSBÕ±Õ¸Õ£Õ¹  · 技术社区  · 14 年前

    任何一个工作超过一周的C程序员都会遇到由于调用而导致的崩溃。 printf 格式说明符多于实际参数,例如:

    printf("Gonna %s and %s, %s!", "crash", "burn");
    

    但是,当你通过时,是否也会发生类似的坏事? 太多 printf的参数?

    printf("Gonna %s and %s!", "crash", "burn", "dude");
    

    我对x86/X64程序集的了解使我相信这是无害的,尽管我不相信我没有遗漏某些边缘条件,而且我不知道其他架构。这种情况是否保证是无害的,或者这里是否也存在可能导致撞车的陷阱?

    5 回复  |  直到 7 年前
        1
  •  14
  •   kingledion    7 年前

    你可能知道printf函数的原型是这样的

    int printf(const char *format, ...);
    

    更完整的版本应该是

    int __cdecl printf(const char *format, ...);
    

    这个 __cdecl 定义“调用约定”,与其他内容一起描述如何处理参数。在这种情况下,它意味着参数被推到堆栈上,并且由进行调用的函数清除堆栈。

    一个替代方案 _cdecl __stdcall 还有其他的。用 Y-STDCALL 约定是将参数推送到堆栈上并由调用的函数清除。然而,据我所知,这是不可能的 Y-STDCALL 函数接受变量个数的参数。这是有道理的,因为它不知道要清理多少堆栈。

    它的长与短是指 γ-CDDEL 函数可以安全地传递所需的任意多个参数,因为清除是在生成调用的代码中执行的。如果你把太多的论点传给 Y-STDCALL 函数它会导致堆栈损坏。一个可能发生这种情况的例子是,如果您的原型不正确。

    有关呼叫约定的更多信息,请访问维基百科。 here .

        2
  •  32
  •   John Bode    14 年前

    Online C Draft Standard (n1256) ,第7.19.6.1节,第2段:

    fprintf函数在指定后续参数的格式所指向的字符串的控制下,将输出写入流所指向的流 已转换为输出。如果格式的参数不足,则行为为 未定义。 如果在参数保持不变的情况下耗尽格式,则多余的参数为 已计算(一如既往),但被忽略。 fprintf函数在以下情况下返回: 遇到格式字符串的结尾。

    其他人的行为 *printf() 除了 vprintf() (显然)。

        3
  •  3
  •   MartyIX    14 年前

    所有参数将被推送到堆栈上,如果堆栈帧被删除,则将被删除。这种行为独立于特定的处理器。(我只记得70年代设计的没有堆栈的大型机)所以,第二个例子不会失败。

        4
  •  3
  •   Ned Batchelder    14 年前

    printf 用于接受任意数量的参数。然后,printf读取格式说明符(第一个参数),并根据需要从参数列表中提取参数。这就是为什么参数太少会崩溃的原因:代码只是开始使用不存在的参数、访问不存在的内存或其他一些糟糕的事情。但由于参数太多,多余的参数将被忽略。格式说明符使用的参数将少于传入的参数。

        5
  •  -2
  •   jfs    14 年前

    注释:GCC和Clang都会发出警告:

    $ clang main.c 
    main.c:4:29: warning: more '%' conversions than data arguments [-Wformat]
      printf("Gonna %s and %s, %s!", "crash", "burn");
                               ~^
    main.c:5:47: warning: data argument not used by format string 
                          [-Wformat-extra-args]
      printf("Gonna %s and %s!", "crash", "burn", "dude");
             ~~~~~~~~~~~~~~~~~~                   ^
    2 warnings generated.