为什么不匹配的printf未定义行为的转换说明论点? [英] Why are arguments which do not match the conversion specifier in printf undefined behavior?

查看:176
本文介绍了为什么不匹配的printf未定义行为的转换说明论点?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在两个C(n1570 7.21.6.1/10)和C ++(由包含C标准库)是未定义的行为提供一个参数的printf的类型不匹配的转换规范。一个简单的例子:

In both C (n1570 7.21.6.1/10) and C++ (by inclusion of the C standard library) it is undefined behavior to provide an argument to printf whose type does not match its conversion specification. A simple example:

printf("%d", 1.9)

格式字符串指定一个int,而参数是一个浮点类型。

The format string specifies an int, while the argument is a floating point type.

此问题是由用户是谁遇到遗产code与转换不匹配的丰富,这显然没有损害,参见问题的启发未定义行为在理论上和实践中

This question is inspired by the question of a user who encountered legacy code with an abundance of conversion mismatches which apparently did no harm, cf. undefined behaviour in theory and in practice.

声明一个单纯的格式不符UB似乎激烈在第一。很显然,在输出的可能是错的,这取决于搞什么确切的不匹配,参数类型,字节顺序,可能堆栈布局等问题。这延伸,正如一位​​评论家那里指出的​​那样,也对后续(或甚至previous?)参数。但是,这还远远没有一般UB。就个人而言,我从来没有遇到过任何东西,但预期错误的输出。

Declaring a mere format mismatch UB seems drastic at first. It is clear that the output can be wrong, depending on things like the exact mismatch, argument types, endianness, possibly stack layout and other issues. This extends, as one commentator there pointed out, also to subsequent (or even previous?) arguments. But that is far from general UB. Personally, I never encountered anything else but the expected wrong output.

要大胆猜测,我会排除对齐问题。我可以想像的是,提供格式字符串,它与可能让读的printf 超出了堆栈小的实际参数使得printf的期待大数据在一起,但我没有在var更深入的了解ARGS机制和具体的printf实现细节来验证。

To venture a guess, I would exclude alignment issues. What I can imagine is that providing a format string which makes printf expect large data together with small actual arguments possibly lets printf read beyond the stack, but I lack deeper insight in the var args mechanism and specific printf implementation details to verify that.

我有一个快速浏览一下<一个href=\"https://sourceware.org/git/?p=glibc.git;a=blob;f=stdio-common/vfprintf.c;h=fc370e8cbc4e9652a2ed377b1c6f2324f15b1bf9;hb=3321010338384ecdc6633a8b032bb0ed6aa9b19a\"相对=nofollow> printf的来源的,但他们是pretty不透明的普通读者。

I had a quick look at the printf sources, but they are pretty opaque to the casual reader.

所以我的问题:什么是错配对转换符和参数的特殊危险的printf 这使得它UB

Therefore my question: What are the specific dangers of mis-matching conversion specifiers and arguments in printf which make it UB?

推荐答案

有些编译器的方式,允许实现可变参数的格式
类型的参数来进行验证;由于具有不正确的程序陷阱
用法可能比可能有它的输出貌似有效的,但是,错了更好
信息,有些平台可能会选择这样做。

Some compilers may implement variable-format arguments in a way that allows the types of arguments to be validated; since having a program trap on incorrect usage may be better than possibly having it output seemingly-valid-but-wrong information, some platforms may choose to do that.

由于陷阱的行为是C标准的领域之外,任何行动
这可能会振振有词陷阱被列为调用未定义的行为。

Because the behavior of traps is outside the realm of the C Standard, any action which might plausibly trap is classified as invoking Undefined Behavior.

注意,实现的可能性诱捕基于不正确的格式意味着行为被认为是不确定的,即使在预期的类型和实际传递类型具有相同的重presentation情况下,除了相同的那个符号和无符号数秩是可以互换的,如果他们持有的值是通用的[即在范围之内如果一个长持有23,它可能与%LX输出,但不是以%X,即使Int和长的大小相同。

Note that the possibility of implementations trapping based on incorrect formatting means that behavior is considered undefined even in cases where the expected type and the actual passed type have the same representation, except that signed and unsigned numbers of the same rank are interchangeable if the values they hold are within the range which is common to both [i.e. if a "long" holds 23, it may be output with "%lX" but not with "%X" even if "int" and "long" are the same size].

还要注意的是C89委员会介绍了菲亚特,这仍然是这一天,其中规定的规则,即使Int和长具有相同的格式,在code:

Note also that the C89 committee introduced a rule by fiat, which remains to this day, which states that even if "int" and "long" have the same format, the code:

long foo=23;
int *u = &foo;
(*u)++;

调用未定义行为,因为它会导致写着类型长被读作类型为INT的信息(行为也将如果它是类型为无符号整型未定义)。由于%X格式说明会导致数据被读取类型无符号整型,传递的数据类型长几乎肯定会导致数据存储在某个地方为长,但后来读类型​​无符号INT,这样的行为就几乎可能违反上述规则。

invokes Undefined Behavior since it causes information which was written as type "long" to be read as type "int" (behavior would also be Undefined if it was type "unsigned int"). Since a "%X" format specifier would cause data to be read as type "unsigned int", passing the data as type "long" would almost certainly cause the data to be stored somewhere as "long" but subsequently read as type "unsigned int", such behavior would almost likely violate the aforementioned rule.

这篇关于为什么不匹配的printf未定义行为的转换说明论点?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆