<分区>
某些常见的编程语言,尤其是 C 和 C++,具有强烈的未定义行为概念:当您尝试执行超出预期使用方式的某些操作时,这会导致未定义行为。
如果发生未定义的行为,编译器可以做它想做的任何事情(包括什么都不做,“时间旅行”等)。
我的问题是:为什么存在这种未定义行为的概念?据我所知,如果不是导致未定义的行为,而是使用其预期用途之外的操作会导致大量错误,一个版本的编译器停止工作的程序停止在下一个版本的编译器上工作等,将被阻止编译错误。
为什么事情不是这样的?
<分区>
某些常见的编程语言,尤其是 C 和 C++,具有强烈的未定义行为概念:当您尝试执行超出预期使用方式的某些操作时,这会导致未定义行为。
如果发生未定义的行为,编译器可以做它想做的任何事情(包括什么都不做,“时间旅行”等)。
我的问题是:为什么存在这种未定义行为的概念?据我所知,如果不是导致未定义的行为,而是使用其预期用途之外的操作会导致大量错误,一个版本的编译器停止工作的程序停止在下一个版本的编译器上工作等,将被阻止编译错误。
为什么事情不是这样的?
最佳答案
Why does this notion of undefined behaviour exist?
允许语言/库尽可能高效地在各种不同的计算机体系结构上实现(- 可能在 C 的情况下 - 同时允许实现保持简单)。
if instead of causing undefined behaviour, using the operations outside of their intended use would cause a compilation error
在大多数未定义行为的情况下,一般来说,要证明所有程序在编译时都存在未定义行为是不可能的,或者在资源上非常昂贵。
一些 案例可以证明一些 程序,但不可能指定哪些案例是详尽无遗的,因此标准不会尝试这样做所以。尽管如此,一些编译器足够聪明,可以识别一些简单的 UB 情况,并且这些编译器会警告程序员。示例:
int arr[10];
return arr[10];
这个程序有未定义的行为。我测试的特定版本的 GCC 显示:
warning: array subscript 10 is above array bounds of 'int [10]' [-Warray-bounds]
忽略这样的警告可不是什么好主意。
具有未定义行为的更典型的替代方法是在这种情况下定义错误处理,例如抛出异常(例如比较 Java,其中访问空引用会导致 java.lang.NullPointerException 类型的异常
被抛出)。但是检查明确定义的行为的先决条件比不检查要慢。
通过不检查前置条件,该语言为程序员提供了自行证明正确性的选项,从而避免了在已证明不需要的程序中进行检查的运行时开销。事实上,这种力量伴随着巨大的责任。
如今,使用工具 (example) 可以在一定程度上减轻证明程序定义良好的负担,这些工具添加了一些运行时检查,并在检查失败时巧妙地终止程序。
关于c++ - 为什么 'undefined behaviour'存在?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51557895/