除以零后没有运行时错误

No Runtime error after divison by zero

我正在使用 Microsoft Visual C++ 2010 我有以下代码,如您所见,我将 1 除以零

#include <cstdio>

int main()
{   
   int x;
   x = 0;
   1/x;

   while (1) {
      std::printf("RUNNING!!\n");
   }
}

令人惊讶的是,我没有发现任何 运行 时间错误,程序继续执行并显示 运行!!

所以我的问题是为什么“1/x”不被视为 运行 时间错误,为什么程序不停止?

相反,您为什么认为应该是运行时错误?没有规定强制执行。

除以零是未定义。在这种情况下,似乎因为它可能在编译时被捕获,所以您的编译器只是简单地忽略了该操作……很可能是因为您从未使用过它的 "result".

因此,该程序运行并可能不输出任何内容:

int main()
{
    int x = 0;
    1/x;
}

而我预计 程序会导致系统级算术异常:

#include <iostream>

int main()
{
    int x = 0;
    int y = 1/x;

    std::cout << y << '\n';
}

一般来说,当您有未定义的行为时,不要期待任何事情。不要指望你的程序"work",不要指望它产生有意义的输出,不要指望它不会phone你的前妻并撤销对你的宠物鸡的合法监护权,不要'期望它会导致您想要的错误。

您没有将 1/x 的评估分配给另一个变量。这就是您没有收到运行时错误的原因。

如果您像这样修改代码 -

int r;
r = 1/x;

然后程序因错误停止。

来自笔记

Stroustrup says, in "The Design and Evolution of C++" (Addison Wesley, 1994), "low-level events, such as arithmetic overflows and divide by zero, are assumed to be handled by a dedicated lower-level mechanism rather than by exceptions. This enables C++ to match the behaviour of other languages when it comes to arithmetic. It also avoids the problems that occur on heavily pipelined architectures where events such as divide by zero are asynchronous."`


So my question why "1/x" is not considered a run time error

您没有将 1/x 的值分配给任何变量,因此您会收到任何 运行 时间错误。将它分配给一个变量,你会得到一个 运行 时间错误。

作为对其他人的补充,我注意到一些关于 "getting or not a run-time error" 的评论让我想到了对模棱两可的术语的误解。

在普通的计算机科学中,"runtime error" 不再是人类大脑的计算机语言(简单的英语)的意思:以及在 "program execution" 期间注意到的错误。

所以是的,在信号 "runtime error" 之后从 OS 获取转储。至少对于英语来说。

但这与 std::runtime_error 无关,即当一个错误被 在他们自己的代码中.

术语 "exception" 也含糊不清:在 OS 术语中,它是 "rescue code" 一个适当的 OS driver 回答 CPU 硬件陷阱。在 C++ 中,要么是表示所有标准库错误的基础 class,要么是 throw 语句的任何值主题。

这里的要点是,整数除以零 不是 标准库实现检测到的错误:C++ 语言认为基本整数算术是托管的原语环境。在大多数平台中,operator/(int,int) 是通过 DIV 汇编程序指令实现的(至少在大多数 CPU 上是这样),带有 0 操作数的 DIV 由CPU 微码作为 CPU 异常,产生由 OS(或特定的 OS driver)。 C++ 编译器(和生成的可执行文件)中没有任何东西知道 DIV 评估期间发生了什么(因为它是 CPU 的内部),所以没有 throw 可以编写的语句,因此没有 std::exception (或任何其他 C++ 类型)可以捕获。只是一个可以替换的操作系统 driver,并且默认情况下会终止应用程序。

这与调用 main(调用 exit)的 C++ 启动代码中的等效默认值 catch(...) 非常相似,因此是另一个混​​淆源。

更复杂的是,编译器优化可以丢弃任何未产生已用结果的操作,使一切变得甚至不可见。

所以,为了让编译器不丢弃操作,必须输出除法结果。完成后,会观察到产生 OS 信号的 CPU 陷阱。这是 - 在简单的英语中 "error at run-time",但不是 C++ std::runtime_error,因为在除法运算符实现中不存在这样的 throw 语句。