2016-11-19 69 views
-1

这段代码有什么问题?EXC_BAD_ACCESS当调用vprintf()

#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,其中至少打印垃圾,我得到EXC_BAD_ACCESS在调用vprintf如下所示:

enter image description here

有没有什么办法可以使这项工作? 谢谢!

更新:我的理解是通过调用数错误的参数的函数得到了一个未定义的行为,但我想myprintf表现就像printf做(没有崩溃)。那可能吗?在拨打vprintf以避免异常之前,有什么方法可以检查参数吗?

UPDATE 2:我想我现在明白了,感谢所有的评论和回答。对于这个非常简单的例子,我认为是更好地使用宏,这向主叫点未能快速和崩溃:

enter image description here

+0

“printf,它至少打印垃圾”。这不是保证的行为。当您故意将代码中的错误添加到具有未定义行为的代码中时,您无法期望它“至少打印垃圾”。 UB意味着行为是不可预测的。它可以立即崩溃,它可以后来崩溃,它可以打印垃圾,它可以打印什么,... – kaylum

+1

[是否“未定义行为”真的允许*发生任何事情?](http://stackoverflow.com/questions/ 32132574/does-undefined-behavior-really-permit-anything-to-happen) – kaylum

+0

@kaylum我更新了我的问题,因为我想知道是否有一种方法可以让我的函数的行为像'printf',在它的未定义的方式。从你的角度来看...如果调用者传递错误的参数就足够了,那么记录该行为是不确定的?谢谢! – cromandini

回答

1

Undefined意味着不可预知的。在一次运行中printf可能会产生垃圾,而在另一次运行中则可能产生EXC_BAD_ACCESS。您无法复制undefined behavior。在这种情况下,格式字符串中的%s字词表示printf需要查找C字符串。根据你的libc实现,当你没有指定第二个参数时,它可能会在某处找到它。如果碰巧在这个指针不远处发现空字符,你会得到垃圾输出。如果不是,printf将继续搜索字符串的末尾,直到它超出分配给程序的内存范围,您将获得EXC_BAD_ACCESS

0

这是不可能的 - 至少不是以便携的方式 - 来确定传递给函数的参数数量。格式说明符是printf确定从堆栈中弹出多少个值的唯一方式,因此输入错误的格式说明符会导致未定义的行为。这只是你需要学习然后继续前进的C语言中的一个。

通过试图“纠正”这样的事情,你可能会让代码更难读,难以让其他人理解。

0

有没有什么办法可以在调用vprintf之前检查参数以避免异常?

只是一个:认真编译器的警告,并消除警告指出你的编程错误。

请参阅:现在变得越来越冬季,街道上会有泥土和积雪(至少在欧洲),所以您有自己喜欢的车库将冬季轮胎安装到保时捷上。在这个漂亮的车,你发现在仪表板下面贴的回报(放在那里由车库):

enter image description here

(APX100英里/小时)

该标签提醒您,那新装冬季轮胎不是支持汽车的最高速度。

现在,当轮胎即将破裂时,您不会开得更快,因为车胎会停下来,不是吗?

这取决于你,司机尊重这个警告!

;-)

相关问题