为什么在 C 中允许未定义的行为 [英] Why is undefined behaviour allowed in C

查看:30
本文介绍了为什么在 C 中允许未定义的行为的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我最近一直在努力学习 C.来自 Java,令我惊讶的是您可以执行声明为未定义"的某些操作.

I have been messing around trying to learn C lately. Coming from Java, it surprised me that you can perform certain operations declared as "undefined".

这对我来说似乎非常不安全.我知道程序员有责任不执行未定义的操作,但为什么甚至允许它开始呢?例如,为什么编译器没有捕捉到数组索引越界,甚至是悬空指针?您最终只是访问了本不应该访问的内存块,而没有(明显的)充分理由.

This just seems extremely unsafe to me. I understand it is the programmer's responsibility not to perform undefined operations, but why is it even allowed to start with? Why does the compiler not catch, for instance, array indices out of bounds, or even dangling pointers? You just end up accessing blocks of memory you never should access, with no (apparent) good reason.

相比之下,Java 使更加确定你不会做任何事情愚蠢,像热蛋糕一样抛出异常.

As a comparison, Java makes extra sure you don't do anything stupid, throwing Exceptions around like hot cakes.

这肯定是有原因的吗?这是什么?

Surely there must be a reason why this is allowed? What is it?

ANSWER:据我所知,主要原因是性能.此外,Java 确实有未定义的行为,尽管没有这样标记.

ANSWER: To my understanding, the main reason is performance. Also, Java does have undefined behaviours, although not labeled as such.

C 的限制问题

推荐答案

最初,大多数未定义行为形式表示某些实现可能会捕获的内容,但其他实现可能不会.因为标准的作者无法预测平台在发生陷阱时可能会做的所有事情(包括,从字面上看,系统会发出警报并锁定直到操作员手动清除故障),陷阱的后果不属于 C 标准的管辖范围,因此几乎每个平台可能会导致陷阱的行为——从标准的角度来看——都被视为未定义行为".

Originally, most forms of Undefined Behavior represented things which some implementations might trap, but other implementations might not. Because there was no way for the authors of the Standard to predict all the things a platform might do in case of a trap (including, literally, the possibility that a system would sound an alarm and lock up until an operator manually cleared the fault), the consequences of traps fell outside the jurisdiction of the C Standard, and thus almost every action for which some platform might conceivably cause a trap is--from the point of view of the Standard--considered "Undefined Behavior".

这不应被视为暗示标准的作者不相信实现应该在实际可行时尝试对此类事情采取明智的行为.例如,C89 标准的作者指出,那个时代的大多数当前系统都会定义以下行为:

That should not be taken to imply that the authors of the Standard didn't believe implementations should try to behave sensibly for such things when practical. The authors of the C89 Standard noted, for example, that the majority of current systems of that era would define behavior for:

/* Assume USmall is half the size of "int" */
unsigned mult(USmall x, USmall y) { return x*y; }

在所有情况下,包括 x 和 y 的数学乘积在 INT_MAX+1 和 UINT_MAX 之间的情况,都等价于 (unsigned)x*y;.我认为没有理由相信他们不会预期这种趋势会持续下去.

which would in all cases, including those where the mathematical product of x and y was between INT_MAX+1 and UINT_MAX, be equivalent to (unsigned)x*y;. I see no reason to believe they wouldn't have expected that trend to continue.

不幸的是,一种基于修正主义观点的新哲学变得流行起来,即编译器编写者只支持标准未强制要求的情况下的有用行为,因为他们太简单了,无法做任何其他事情.例如,在 gcc 中,使用优化级别 2 但没有其他非默认选项,上面的mult"例程有时会在乘积介于 0x80000000u 和 0xFFFFFFFFu 之间的情况下生成虚假代码,即使在此类计算的平台上运行时也是如此历史上有工作.据说这是以优化"的名义进行的;了解此类技术最终执行的优化"中有多少实际上是有用的,并且无法通过更安全的方式实现,这将会很有趣.

Unfortunately, a new philosophy has become fashionable, based on the revisionist viewpoint that compiler writers only supported useful behaviors in cases not mandated by the Standard because they were too unsophisticated to do anything else. In gcc, for example, using optimization level 2 but no other non-default options, the above "mult" routine will sometimes generate bogus code in cases where the product would be between 0x80000000u and 0xFFFFFFFFu, even when running on platforms where such computations would historically have worked. This is supposedly being done in the name of "optimization"; it would be interesting to know how many of the "optimizations" such techniques end up performing are actually useful and could not have been achieved via safer means.

从历史上看,Undefined Behavior 是 C 编译器公开底层平台行为的许可证;在底层平台的行为符合程序员的需求的情况下,这允许程序员的要求以机器代码表达,而不是一切都必须按照标准定义的方式完成.然而,最近,它被解释为编译器实现行为的许可,这些行为不仅与底层平台中的任何内容无关,也与任何合理的程序员期望无关,甚至不受时间和因果关系定律的约束.

Historically, Undefined Behavior was a license for a C compiler to expose the behavior of the underlying platform; in cases where the underlying platform's behavior fit the programmer's needs, this allowed the programmer's requirements to be expressed in machine code more efficiently than if everything had to be done in ways defined by the Standard. Lately, however, it has been interpreted as license for compilers to implement behaviors which not only bear no relation to anything in the underlying platform nor to any plausible programmer expectations, but aren't even bound by laws of time and causality.

这篇关于为什么在 C 中允许未定义的行为的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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