简体   繁体   English

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

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

I was reading this: 我在读这个:

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

when I saw two sentences that make no sense to me towards the end. 当我看到最后两个句子对我来说毫无意义时。

this function never throws exceptions. 此函数从不抛出异常。

vs.

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. 如果str没有指向有效的C字符串,或者转换后的值超出int可表示的值范围,则它将导致未定义的行为。

If the behavior of a bad parse is undefined, doesn't that mean all bets are off, and it's entirely possible for an exception to be raised? 如果错误解析的行为是不确定的,那是否就意味着所有赌注都没有了,是否有可能引发异常? Or does this mean "undefined except that the runtime promises not to throw an exception"? 还是这意味着“未定义,但运行时承诺不会引发异常”?

When the C or C++ standards speak of undefined behaviour, they mean that the consequence of running the program as a whole is undefined, not that the result or consequence of executing a particular construct is unspecified. 当C或C ++标准谈到未定义的行为时,它们意味着未定义整体运行程序的结果,而不是未指定执行特定构造的结果或结果。 It is even possible that execution of the program will be derailed before the erroneous construct is executed . 甚至有可能在执行错误的构造之前使程序的执行脱轨。 For example, the runtime may detect that a pointer which will later be provided to atoi is invalid, and interrupt execution at that point. 例如,运行时可以检测到稍后将提供给atoi的指针无效,并在那一点中断执行。 If the compiler could prove that this will happen, it could even fail to compile the program. 如果编译器可以证明会发生这种情况,则它甚至可能无法编译程序。 The standard(s) explicitly make no restriction on what might be the result of the execution of a program which engenders undefined behaviour. 该标准明确地不限制执行导致不确定行为的程序的结果。

Having said that, it is unlikely that calling atoi with an invalid argument will raise an exception. 话虽如此,用无效的参数调用atoi不太可能引发异常。 The most likely consequences of integer overflow are truncation, clamping, or a trap/signal (which is not an exception); 整数溢出的最可能后果是截断,钳位或陷阱/信号(这也不例外); the most likely consequence of an invalid pointer is a segfault, which (on a Unix-like system) is a signal; 无效指针最有可能导致的后果是段错误(在类Unix系统上)是一个信号; as above, signals are not exceptions. 如上所述,信号也不例外。

Nonetheless, it is not impossible that a given implementation may choose to raise an exception on receipt of a signal produced by a segfault or an integer overflow. 但是,给定的实现可能会选择在收到由段错误或整数溢出产生的信号时引发异常。 Such an implementation would presumably attempt to ensure that an exception so raised could be caught, even if the signal is raised during execution of a function declared as not throwing. 这样的实现大概会试图确保可以捕获这样引发的异常,即使在执行声明为未抛出的函数的过程中引发了信号也是如此。 (Such an implementation would probably also document which exception would be raised in such cases, since an implementation is free to define the consequence of behaviour undefined by the standard.) If that attempt failed, and the exception was instead punted higher up the exception stack than was desired, that would still fall inside the complete lack of standard specification; (这样的实现可能还会记录在这种情况下会引发哪个异常,因为实现可以自由定义标准未定义的行为的结果。)如果该尝试失败,则将异常从异常堆栈上移至更高的位置超出了期望,这仍然属于完全缺乏标准规范的范围之内; the worst the implementation could be accused of would be failing to implement its own extension to the standard, which is a quality-of-implementation issue. 可能被指责的最糟糕的情况是未能实现自己对标准的扩展,这是实现质量的问题。


Language-lawyerly addition: 语言上合法的添加:

Obligatory standard quote: (§1.9 [intro.execution] , paragraph 5) 强制性标准报价单:(第1.9节[介绍执行]第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). 但是,如果任何这样的执行包含未定义的操作,则此国际标准对使用该输入执行该程序的实现没有任何要求(甚至不涉及第一个未定义的操作之前的操作)。

Any description of program execution made by the standard ("shall not throw exceptions", for example) needs to be interpreted within the context of that paragraph. 标准对程序执行的任何描述(例如“不得抛出异常”)都需要在该段落的上下文中进行解释。

The C++ standard defines the term "undefined" to (in effect) mean that the C++ standard does not place any constraints on what happens. C ++标准将术语“未定义”定义为(实际上)意味着C ++标准对发生的事情没有任何限制。

A statement that a function does not throw exceptions means that the specification of the function does not include throwing any exceptions. 函数不引发异常的声明意味着该函数的规范不包括引发任何异常。

Yes, it is possible for an implementer (of a compiler or an implementation of the standard library) to throw an exception in a circumstance that is undefined according to the standard. 是的,(标准的编译器或实现的)实现者有可能在根据标准未定义的情况下引发异常。 After all, throwing an exception is a perfectly acceptable decision by an implementer if the standard does not constrain what is permitted to occur. 毕竟,如果标准不限制允许发生什么,则抛出异常是实现者完全可接受的决定。

However, that does not mean instances of undefined behaviour must result in exceptions being thrown. 但是,这并不意味着未定义行为的实例必须导致引发异常。 Nor does it mean that a thrown exception indicates that some instance of undefined behaviour has occurred. 这也不意味着抛出异常表示发生了一些未定义行为的实例。

It does mean that two different implementations (eg different versions of some vendor's product, or products from different vendors) can do completely different things in response to an instance of undefined behaviour. 这确实意味着,两种不同的实现方式(例如某个供应商产品的不同版本,或来自不同供应商的产品)可以对未定义行为的实例做出完全不同的操作。 One can throw an exception of some form. 一个人可以抛出某种形式的异常。 Another can reformat the systems hard drive (although, fortunately, implementations that deliberately do this are rare). 另一个可以重新格式化系统硬盘驱动器(尽管幸运的是,故意执行此操作的实现很少)。 Because the behaviour is undefined according to the standard, whatever happens is correct - at least according to the standard. 因为行为是根据标准未定义的,所以无论发生什么都是正确的-至少根据标准。

When it says that it does not throw an exception, you should read that - do not expect an exception to be raised when a problem arises. 当它说它没有引发异常时,您应该阅读该内容-不要期望在出现问题时引发异常。

Of course the exception may be raised by a pure luck, but it is very unlikely to happen. 当然,由于纯粹的运气可能会引发例外,但这种情况极不可能发生。 You shouldn't rely on it. 你不应该依赖它。

All guarantees about the function are only valid as long as you pass a valid pointer to a string. 仅当您将有效的指针传递给字符串时,有关该函数的所有保证才有效。

If you don't, anything may happen, including throwing an exception. 如果不这样做,可能会发生任何事情,包括引发异常。

In other words, the part about unspecified behavior takes priority over the part about the regular behavior. 换句话说,关于未指定行为的部分优先于关于常规行为的部分。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM