2

我理解编译器/解释器语言扩展的原因,但为什么没有有效定义的行为允许静默失败/做奇怪的事情而不是抛出编译器错误?是因为编译器捕获它们的额外困难(不可能或只是耗时)吗?

PS 哪些语言有未定义的行为,哪些没有?

PPS 是否存在未定义行为的实例,这并非不可能/在编译中需要很长时间才能捕获,如果是这样,是否有任何充分的理由/借口。

4

3 回答 3

4

未定义行为的概念在 C 和 C++ 等语言中是必需的,因为检测导致它的条件是不可能的或过于昂贵。以这段代码为例:

int * p = new int(0);
// lots of conditional code, somewhere in which we do
int * q = p;
// lots more conditional code, somewhere in which we do
delete p;
// even more conditional code, somewhere in which we do
delete q;

这里指针已被删除两次,导致未定义的行为。对于像 C 或 C++ 这样的语言来说,检测错误太难了。

于 2010-05-10T11:41:58.820 回答
3

很大程度上是因为,为了完成某些目的,这是必要的。例如,C 和 C++ 最初用于编写操作系统,包括设备驱动程序之类的东西。为此,他们使用(除其他外)直接访问代表 I/O 设备的特定硬件位置。阻止对这些位置的访问将阻止 C 用于其预期目的(并且 C++ 专门针对允许与 C 相同的所有功能)。

另一个因素是指定语言和指定平台之间的一个非常基本的决定。使用相同的示例,C 和 C++ 都基于有意识的决定,将定义限制在语言中,并将围绕该语言的平台分开。相当多的替代方案(以 Java 和 .NET 作为最明显的例子)指定整个平台。

这两者都反映了对设计态度的基本差异。C 设计的基本准则之一(主要保留在 C++ 中)是“信任程序员”。尽管从未如此直接地陈述过,但 Java 的基本“沙盒”概念是/现在是基于您不应该信任程序员的想法

至于哪些语言有/没有未定义的行为,这是一个肮脏的小秘密:出于所有实际目的,它们都有未定义的行为。一些语言(同样,C 和 C++ 是最好的例子)会付出相当大的努力来指出哪些行为是未定义的,而许多其他语言要么试图声称它不存在(例如 Java),要么大多忽略了许多“黑暗角落” " 它出现的地方(例如,Pascal,大多数 .NET)。

那些声称它不存在的人通常会产生最大的问题。例如,Java 包含许多试图保证一致的浮点结果的规则。在这个过程中,它们使得在相当多的硬件上有效地执行 Java 成为不可能——但浮点结果仍然不能真正保证是一致的。更糟糕的是,他们要求的浮点模型并不完全完美,因此在某些情况下,它会阻止你获得最好的结果(或者至少会让你做很多额外的工作来绕过它的要求)。

To their credit, Sun/Oracle has (finally) started to notice the problem, and is now working on a considerably different floating point model that should be an improvement. I'm not sure if this has been incorporated in Java yet, but I suspect that when/if it is, there will be a fairly substantial "rift" between code for the old model and code for the new model.

于 2010-05-10T15:57:27.937 回答
0

因为不同的操作系统运行方式不同(...),你不能只说“在这种情况下崩溃”,因为这可能是操作系统可以做得更好的事情。

于 2010-05-10T11:45:52.223 回答