前面已经讲过,如果某个异常未被捕捉,会调用std::terminate()函数。当异常处理机制发现堆栈损坏时,或者在由某个异常抛出而导致的堆栈回退过程中,被调用的析构函数企图通过抛出异常而退出时,都会调用std::terminate()函数。通俗地讲,未捕捉的异常是没有为其准备catch()处理函数的异常,或是throw()所执行的析构函数抛出的异常。此异常将造成std::terminate()函数被调用,该函数随即调用std::abort()以终止程序。
未预期的异常由set_unexpected()确定的_unexpected_handler处理。类似情况是,对未捕捉的异常响应是由_uncaught_handler确定,而它可由<exception>中的std::set_terminate()设置:
返回值给出的是通过set_terminate()设置的前一个函数。
提出terminate()的原因是:在少数情况下,必须能用较粗糙的错误处理技术终止异常处理过程。例如,terminate()可能被用于结束某个进程,甚至用于重新初始化一个系统。采用terminate()的意图是作为一种严格限制,当由异常处理机制所实现的错误恢复策略失败之后,应该进入另一个容错策略层次,即可应用之。
通常,按默认的规定,terminate()会调用abort()函数。对大部分用户而言,这是一种正确的选择。特别是在排除错误阶段。
uncaught_handler被假定是不会返回其调用者的,否则terminate()将调用abort()。a-bort()函数表示从程序中非正常退出。若使用exit()函数终止程序,其返回值可以向外围系统表明程序是正常结束还是非正常结束。
在程序因为未捕捉的异常而终止时,是否调用有关的析构函数将由具体实现决定。不调用析构函数是至关重要的,这将使程序能够从排错系统中重新唤醒。在其他系统中,系统的结构决定在检索异常处理器的过程中,不调用析构函数是不可能的。(www.xing528.com)
如果要在发生未捕捉异常时保证进行彻底的清理工作,可以在所有真正需要关注的异常处理器之外,为main()函数添加捕捉一切的处理器。例如,
上述形式的代码即可捕捉程序可能发生的所有异常,除在全局变量的构造和析构中抛出的异常之外,没有办法捕捉全局变量初始化期间抛出的异常。对于非局部静态对象初始化中出现的throw,获取控制的唯一办法是通过set_unexpected(),即应该尽可能地避免全局变量的其他原因。
一旦异常被捕捉,通常无法确定其抛出位置,这也意味着信息的丢失。在有些C++开发环境中,对某些程序和某些开发人员而言,信息的丢失会导致无法捕捉“程序设计本身无法恢复的异常”。
总结
8.1节主要讲述了异常及其相关的部分概念和异常处理的基本原理。请读者认真阅读,对异常处理能有较清楚的认识即可。任何知识的学习均是循序渐进的过程,开始最重要的是了解和理解其基本概念和基本原理,随着今后实践机会和实践经验的逐渐增加,对异常处理的认识会更加深刻。同样,对于C++STL的其他内容也是如此,都需要经历循序渐进的过程。
免责声明:以上内容源自网络,版权归原作者所有,如有侵犯您的原创版权请告知,我们将尽快删除相关内容。