此代码有什么问题?
#include <stdio.h>
#include <stdarg.h>
void myprintf(const char * format, ...) __printflike(1, 2);
int main(int argc, const char * argv[]) {
printf("%s\n");
myprintf("%s\n");
return 0;
}
void myprintf(const char * format, ...) {
if (format) {
va_list arguments;
va_start(arguments, format);
vprintf(format, arguments);
va_end(arguments);
}
}
使用__printflike
我收到了一个很好的警告,例如printf
。但与至少打印垃圾的printf
不同,我在调用vprintf
时获得了EXC_BAD_ACCESS,如下所示:
有什么方法可以让我的工作吗? 谢谢!
更新:据我所知,通过使用错误数量的参数调用函数,我得到了未定义的行为,但我希望myprintf
的行为与printf
一样(没有崩溃)。那可能吗?有没有办法在调用vprintf
之前检查参数以避免异常?
更新2:我想我现在知道了,感谢所有的评论和答案。对于这个非常简单的例子,我认为最好使用一个宏,快速失败并在调用点崩溃:
答案 0 :(得分:1)
Undefined
意味着不可预测。在一次运行中,printf
可能会产生垃圾,而在另一次运行中,它可能会产生EXC_BAD_ACCESS
。您无法重现undefined behavior
。在这种特殊情况下,格式化字符串中的%s
术语表示printf
需要查找C字符串。根据您的libc实现,当您未指定第二个参数时,它可能会在某处找到它。如果发现在距离此指针不远的地方发现了一个空字符,则会得到垃圾输出。如果没有,printf
将继续搜索字符串的结尾,直到它超出分配给您的程序的内存范围,然后获得EXC_BAD_ACCESS
。
答案 1 :(得分:0)
不可能 - 至少不是以可移植的方式 - 确定传递给函数的参数数量。格式说明符是printf
确定从堆栈中弹出多少个值的唯一方法,因此输入错误的格式说明符会为您提供未定义的行为。这只是你需要学习然后继续学习的C之一。
通过尝试&#34;纠正&#34;像这样的事情你可能只是让代码更难以理解,而其他人也难以理解。
答案 2 :(得分:0)