如果 C++ 的 atoi() 允许未定义的行为,它如何保证不抛出异常?

How can C++'s atoi() guarantee not to throw an exception if it allows undefined behavior?

我正在读这个:

http://www.cplusplus.com/reference/cstdlib/atoi/

当我在最后看到两个对我来说毫无意义的句子时。

this function never throws exceptions.

对比

If str does not point to a valid C-string, or if the converted value would be out of the range of values representable by an int, it causes undefined behavior.

如果错误解析的行为未定义,这是否意味着所有赌注都已关闭,并且完全有可能引发异常?或者这是否意味着 "undefined except that the runtime promises not to throw an exception"?

当它说它不会抛出异常时,您应该阅读 - 不要期望在出现问题时会引发异常。

当然,这种异常也可能是纯粹的运气引发的,但这种情况发生的可能性很小。你不应该依赖它。

当 C 或 C++ 标准谈到未定义的行为时,它们意味着 运行 程序的结果 作为一个整体 是未定义的,而不是结果或执行特定构造的结果未指定。甚至有可能程序的执行会在执行错误构造之前出轨 。例如,运行时可能检测到稍后将提供给 atoi 的指针无效,并在该点中断执行。如果编译器可以证明这会发生,它甚至可能无法编译程序。标准明确没有限制执行程序可能产生未定义行为的结果。

话虽如此,使用无效参数调用 atoi 不太可能引发异常。整数溢出最可能的后果是截断、钳位或 trap/signal(这也不例外);无效指针最可能的后果是段错误,它(在类 Unix 系统上)是一个信号;如上所述,信号也不例外。

尽管如此,给定的实现可能会选择在收到由段错误或整数溢出产生的信号时引发异常。这样的实现可能会尝试确保可以捕获如此引发的异常,即使在执行声明为不抛出的函数期间引发信号也是如此。 (这样的实现可能还会记录在这种情况下会引发哪个异常,因为实现可以自由定义标准未定义的行为的后果。)如果该尝试失败,则将异常放在异常堆栈的更高位置超出预期,这仍然属于完全缺乏标准规范;实施可能被指责的最坏情况是未能实施自己对标准的扩展,这是实施质量问题。


语言-律师加法:

强制性标准引用:(§1.9 [intro.execution],第 5 段)

A conforming implementation executing a well-formed program shall produce the same observable behavior as one of the possible executions of the corresponding instance of the abstract machine with the same program and the same input. However, if any such execution contains an undefined operation, this International Standard places no requirement on the implementation executing that program with that input (not even with regard to operations preceding the first undefined operation).

标准对程序执行的任何描述(例如“不应抛出异常”)都需要在该段的上下文中进行解释。

C++ 标准将术语 "undefined" 定义为(实际上)意味着 C++ 标准不对所发生的事情施加任何限制。

一个函数不抛出异常的声明意味着该函数的规范不包括抛出任何异常。

是的,(编译器的实现者或标准库的实现者)有可能在标准未定义的情况下抛出异常。毕竟,如果标准不限制允许发生的事情,抛出异常是实现者完全可以接受的决定。

然而,这并不意味着未定义行为的实例必须导致抛出异常。这也不意味着抛出的异常表示发生了某些未定义行为的实例。

这确实意味着两种不同的实现(例如,某些供应商产品的不同版本,或来自不同供应商的产品)可以做完全不同的事情来响应未定义行为的实例。可以抛出某种形式的异常。另一个可以重新格式化系统硬盘驱动器(尽管幸运的是,故意这样做的实现很少见)。因为根据标准未定义行为,所以无论发生什么都是正确的 - 至少根据标准。

关于该函数的所有保证仅在您传递一个有效的字符串指针时才有效。

如果不这样做,可能会发生任何事情,包括抛出异常。

换句话说,关于未指定行为的部分优先于关于常规行为的部分。