我使用的是Microsoft Visual C ++ 2010 我有以下代码,其中我将你除以1除以
#include <cstdio>
int main()
{
int x;
x = 0;
1/x;
while (1) {
std::printf("RUNNING!!\n");
}
}
并且令人惊讶的是我没有发现任何运行时错误,程序继续执行并显示RUNNING !!
所以我的问题为什么“1 / x”不被认为是运行时错误,为什么程序不会停止?
答案 0 :(得分:6)
相反,为什么你认为应该是运行时错误?没有规定强制要求。
将 undefined 除以零。在这种情况下似乎,因为它可以在编译时被捕获,你的编译器只是忽略了操作...很可能因为你从未使用过它的“结果”。
因此,该程序运行并可能不输出任何内容:
int main()
{
int x = 0;
1/x;
}
虽然我可以指望此程序导致系统级算术异常:
#include <iostream>
int main()
{
int x = 0;
int y = 1/x;
std::cout << y << '\n';
}
通常,当您有未定义的行为时,不要指望任何事情。不要指望你的程序“工作”,不要指望它产生有意义的输出,不要指望它不打电话给你的前妻并取消你的宠物鸡的合法监护权,并且不要指望它会造成你想要的错误。
答案 1 :(得分:2)
您没有将1/x
的评估分配给另一个变量。这就是为什么你没有得到运行时错误。
如果你修改你的代码 -
int r;
r = 1/x;
然后程序因错误而停止。
答案 2 :(得分:1)
来自笔记
Stroustrup在“C ++的设计与演变”(Addison Wesley, 1994),“低级事件,例如算术溢出和除以 零,假定由专用的低级机制处理 而不是例外。这使C ++能够匹配行为 算术时的其他语言。它也避免了 事件发生在严重流水线架构上的问题 例如除以零是异步的。“`
所以我的问题为什么“1 / x”不被视为运行时错误
您没有为任何变量分配1 / x的值,因此您得到任何运行时错误。将其分配给变量,您将收到运行时错误。
答案 3 :(得分:1)
作为对其他人的补充,我注意到一些关于&#34;得到或不是运行时错误的评论&#34;这让我想到了对含糊不清的术语的误解。
在普通计算机科学中,&#34;运行时错误&#34;不再是人类大脑的计算机语言(简单英语)意味着什么:和#34;程序执行期间注意到的错误&#34;。
所以是的,在信号出现&#34;运行时错误&#34;后从操作系统获取转储。至少对于英语而言。
但这与std::runtime_error
有关,这是标准库(或基于标准库的任何其他代码)抛出的std::exception
,当错误是基金时他们自己的代码。
术语&#34;例外&#34;是不明确的:在操作系统术语中,它是&#34;救援代码&#34;适当的OS驱动程序,以应对CPU硬件陷阱。在C ++中,is是表示所有标准库错误的基类,或者是throw语句的任何值主题。
这里的观点是,整数除以零是不标准库实现检测到的错误:C ++语言将基本整数算法视为托管环境的原始算法。在大多数平台中,operator/(int,int)
是通过DIV汇编程序指令(至少在大多数CPU上)实现的,带有0操作数的DIV由CPU微码处理为CPU异常,产生&#34 ;陷阱&#34; (或中断,或平台术语所称的任何内容)由OS(或特定的OS驱动程序)处理。 C ++编译器(以及生成的可执行文件)中没有任何内容可以知道在DIV评估期间发生了什么(因为它在CPU内部),因此没有 throw 语句可以写,因此没有要捕获的std :: exception(或其他任何C ++类型)。只是一个可以替换的操作系统驱动程序,默认情况下终止应用程序。
这是调用main(调用exit)的C ++启动代码中等效默认值catch(...)
的非常相似的行为,因此是另一个混淆源。
为了使更多的事情复杂化,编译器优化可以丢弃任何不产生使用结果的操作,使一切变得不可见。
因此,输出除法结果是必须让编译器不丢弃操作。并且当完成时,观察到产生OS信号的CPU陷阱。这是一个简单的英语&#34;错误在运行时&#34;,但不是C ++ std::runtime_error
,因为在除法运算符实现中不存在这样的throw语句。