除以零后没有运行时错误

No Runtime error after divison by zero

本文关键字:运行时错误      更新时间:2023-10-16

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

#include <cstdio>
int main()
{   
   int x;
   x = 0;
   1/x;
   while (1) {
      std::printf("RUNNING!!n");
   }
}

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

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

相反,为什么您认为应该存在运行时错误?没有规则可以强制要求这样做。

除以

零是未定义的。在这种情况下,因为它可能在编译时被捕获,所以你的编译器只是忽略了这个操作......很可能是因为你从未使用过它的"结果"。

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

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

而我可以期望这个程序会导致系统级算术异常:

#include <iostream>
int main()
{
    int x = 0;
    int y = 1/x;
    std::cout << y << 'n';
}

一般来说,当你有未定义的行为时,不要期待任何事情。不要指望你的程序"工作",不要指望它产生有意义的输出,不要指望它不给你的前妻打电话并取消对你的宠物鸡的合法监护权,不要指望它会导致你想要的错误。

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

如果你像这样修改你的代码——

int r;
r = 1/x;

然后程序因错误而停止。

作为对其他人的补充,我注意到一些关于"是否获得运行时错误"的评论,这让我想到了对模棱两可的术语的误解。

在普通计算机科学中,"运行时错误"不再是人脑的计算机语言(简单的英语(的含义:以及在"程序执行"期间注意到的错误。

所以是的,在信号后从操作系统获取转储是"运行时错误"。至少对于英语来说。

但这与标准库(或基于标准库的任何其他代码(在自己的代码中出现错误时抛出std::runtime_error std::exception有关。

此外,术语"异常"是模棱两可的:在操作系统术语中,它是"救援代码",一个适当的操作系统驱动程序用于回答 CPU 硬件陷阱。 在C++中,is要么是表示所有标准库错误的基类,要么是抛出语句的任何值主题。

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

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

更复杂的是,编译器优化可以丢弃任何未产生使用结果的操作,从而使所有内容变得甚至不可见。

因此,必须输出除法结果,以使编译器不丢弃操作。 当这样做时,会观察到产生操作系统信号的CPU陷阱。用简单的英语来说,这是一个"运行时的错误",但不是C++ std::runtime_error因为除法运算符实现中不存在这样的抛出语句。

来自注释

斯特

劳斯特鲁普在《C++的设计与演变》(艾迪生· 1994(,"低级事件,如算术溢出和除以 零,假设由专用的较低级别机制处理 而不是例外。这使C++能够匹配 其他语言在算术方面。它还避免了 在大量管道化体系结构上发生的问题,其中事件 比如除以零是异步的。`


所以我的问题为什么"1/x"不被视为运行时错误

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