任何已经工作超过一周的C程序员遇到了因printf
使用更多格式说明符而非实际参数调用而导致的崩溃,例如:
printf("Gonna %s and %s, %s!", "crash", "burn");
Run Code Online (Sandbox Code Playgroud)
但是,当你向printf 传递太多参数时,是否会发生类似的坏事?
printf("Gonna %s and %s!", "crash", "burn", "dude");
Run Code Online (Sandbox Code Playgroud)
我对x86/x64程序集的了解使我相信这是无害的,虽然我不相信没有一些边缘条件我缺少,而且我不知道其他架构.这种情况是否保证是无害的,或者这里是否存在潜在的崩溃诱因?
Joh*_*ode 33
在线C草案标准(n1256),第7.19.6.1节,第2段:
fprintf函数将输出写入stream指向的流,在指向格式的字符串的控制下,该格式指定后续参数如何转换为输出.如果格式的参数不足,则行为未定义.如果参数保留时格式已用尽,则会评估多余的参数(一如既往),否则将被忽略.当遇到格式字符串的末尾时,fprintf函数返回.
*printf()
除了vprintf()
(显然)之外,所有其他函数的行为与多余的参数相同.
tor*_*rak 15
你可能知道printf函数的原型就像这样
int printf(const char *format, ...);
Run Code Online (Sandbox Code Playgroud)
实际上是一个更完整的版本
int __cdecl printf(const char *format, ...);
Run Code Online (Sandbox Code Playgroud)
在__cdecl
定义了"调用约定",它与其它东西一起,介绍了参数是如何处理的.在这种情况下,它意味着args被推入堆栈,并且堆栈由进行调用的函数清理.
另一种选择_cdecl
是__stdcall
,还有其他的.根据__stdcall
惯例,参数被压入堆栈并由被调用的函数清理.但是,据我所知,__stdcall
函数不可能接受可变数量的参数.这是有道理的,因为它不知道要清理多少堆栈.
它的长期和短期是,在__cdecl
函数的情况下,它可以安全地传递你想要的多个args,因为清理是在进行调用的代码中执行的.如果你以某种方式向__stdcall
函数传递太多参数,则会导致堆栈损坏.可能发生这种情况的一个例子是你有错误的原型.
有关调用约定的更多信息可以在维基百科上找到.
归档时间: |
|
查看次数: |
31205 次 |
最近记录: |