为什么存在“未定义行为"? [英] Why does 'undefined behaviour' exist?

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

问题描述

某些常见的编程语言,尤其是 C 和 C++,具有未定义行为的强烈概念:当您尝试以超出预期使用方式的方式执行某些操作时,这会导致未定义行为.

Certain common programming languages, most notably C and C++, have the strong notion of undefined behaviour: When you attempt to perform certain operations outside of the way they are intended to be used, this causes undefined behaviour.

如果发生未定义的行为,编译器可以做任何想做的事情(包括什么都不做、时间旅行"等).

If undefined behaviour occurs, a compiler is allowed to do anything (including nothing at all, 'time traveling', etc.) it wants.

我的问题是:为什么存在这种未定义行为的概念?就我所见,如果不是导致未定义的行为,而是使用超出预期用途的操作会导致大量的错误、在一个版本的编译器上运行的程序停止在下一个版本上运行等,则将被阻止编译错误.

My question is: Why does this notion of undefined behaviour exist? As far as I can see, a huge load of bugs, programs that work one one version of a compiler stop working on the next, etc. would be prevented if instead of causing undefined behaviour, using the operations outside of their intended use would cause a compilation error.

为什么事情不是这样?

推荐答案

为什么存在这种未定义行为的概念?

Why does this notion of undefined behaviour exist?

允许语言/库尽可能高效地在各种不同的计算机架构上实现(可能在 C 的情况下,同时允许实现保持简单).

To allow the language / library to be implemented on a variety of different computer architectures as efficiently as possible (- and perhaps in the case of C - while allowing the implementation to remain simple).

如果不是导致未定义的行为,而是使用预期用途之外的操作会导致编译错误

if instead of causing undefined behaviour, using the operations outside of their intended use would cause a compilation error

在大多数未定义行为的情况下,不可能证明所有程序在编译时都存在未定义行为,或者资源成本过高.

In most cases of undefined behaviour, it is impossible - or prohibitively expensive in resources - to prove that undefined behaviour exists at compile time for all programs in general.

某些案例可以证明某些程序,但无法详细说明哪些案例是详尽无遗的,因此标准不会尝试做所以.尽管如此,一些编译器足够聪明,可以识别一些简单的 UB 情况,这些编译器会警告程序员.示例:

Some cases are possible to prove for some programs, but it's not possible to specify which of those cases are exhaustively, and so the standard won't attempt to do so. Nevertheless, some compilers are smart enough to recognize some simple cases of UB, and those compilers will warn the programmer about it. Example:

int arr[10];
return arr[10];

这个程序有未定义的行为.我测试过的特定版本的 GCC 显示:

This program has undefined behaviour. A particular version of GCC that I tested shows:

警告:数组下标 10 高于 'int [10]' [-Warray-bounds] 的数组边界

warning: array subscript 10 is above array bounds of 'int [10]' [-Warray-bounds]

忽略这样的警告并不是一个好主意.

It's hardly a good idea to ignore a warning like this.

具有未定义行为的更典型的替代方法是在这种情况下定义错误处理,例如抛出异常(例如比较 Java,其中访问空引用会导致 java.lang.NullPointerException 类型的异常 被抛出).但是检查明确定义的行为的先决条件比不检查它要慢.

More typical alternative to having undefined behaviour would be to have defined error handling in such cases, such as throwing an exception (compare for example Java, where accessing a null reference causes an exception of type java.lang.NullPointerException to be thrown). But checking for the pre-conditions of well defined behaviour is slower than not checking it.

通过不检查先决条件,该语言为程序员提供了自己证明正确性的选项,从而避免了在被证明不需要的程序中进行检查的运行时开销.事实上,这种权力伴随着巨大的责任.

By not checking for pre-conditions, the language gives the programmer the option of proving the correctness themselves, and thereby avoiding the runtime overhead of the check in a program that was proven to not need it. Indeed, this power comes with a great responsibility.

如今,通过使用工具(example) 添加了一些运行时检查,并在检查失败时巧妙地终止程序.

These days the burden of proving the program's well-definedness can be somewhat alleviated by using tools (example) which add some of those runtime checks, and neatly terminate the program upon failed check.

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

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