如何避免因意外异常导致的问题?

时间:2015-04-02 06:19:56

标签: c++ exception

这是C ++编程中一个不太常见的问题:

程序员A编写一个C ++库(我们称之为Foo),它包含一个程序员B的程序调用方法的漂亮的公共API,以实现他的程序的一部分。使用Foo API时,程序员B会查看文档和头文件,但不会查看.cpp文件,主要是因为拥有公共API的重点是隐藏实现细节。程序员B让他的程序工作,最初一切看起来都不错。

有一天程序正在做它的事情,当Foo代码库内发生异常时导致Foo方法抛出异常。程序员B不知道该Foo方法可能抛出这种类型的异常,因此异常要么不被捕获(并且程序崩溃),要么异常被非常通用的异常处理程序捕获(例如catch(。 ..))并没有得到充分的处理(所以程序做了一些非最佳的事情,比如用隐藏的错误信息建立一个对话框。)

由于我希望我的C ++软件能够健壮,我的问题是,避免上述场景的好方法是什么?要求程序员B读取Foo代码库中的所有.cpp文件(以及Foo调用的任何C ++代码库的所有.cpp文件,以此类推),查找throw语句似乎不是一个合适的解决方案,因为它违反了封装的精神,即使它已经完成,也不能保证将来可能不会添加更多的throw语句。要求程序员A记录所有可能抛出的异常似乎是一个好主意,但实际上程序员A很可能会错过其中的一些,特别是如果他的代码反过来调用另一个可能会或可能不会记录其100%的库可能的例外。

在Java中,有一些支持自动异常处理检查;例如你可以注释你的Java方法来声明它们可能抛出的异常,如果调用代码没有显式处理所有这些异常(或者它自己声明它可能抛出它们),编译失败并且程序员被迫修复他的程序 - 从而防止上述问题情景。另一方面,C ++没有这样的编译时强制执行,这意味着验证C ++程序正确处理所有异常似乎完全取决于程序员和QA团队。但是在一个非平凡的计划中,实际执行这样的验证似乎是不切实际的;是否存在一些技术(自动化或非自动化),通过这些技术,C ++程序员可以确信他们的程序能够以一种被认可的方式处理所有可能抛出的异常? (即使只是一个列出可以从各种调用中抛出的所有异常的程序,我认为 - 至少会有一个已知的可能性列表来检查异常处理代码)

1 个答案:

答案 0 :(得分:2)

首先,这个问题似乎存在很大的困境。直到你发现以下见解。

在涉及异常的情况下,抛出异常,抛出异常以及捕获异常的事实捕获了抛出异常信息的90%以上的重要性。异常的类型很少很重要。

事实证明,我们很少创建可以解决问题的代码并提出补救解决方案。几乎总是代码可以做的唯一有用的事情是报告命令失败及其错误消息。

如果库中使用的异常是从std :: exception派生的,并且支持对what()的有用调用,那么当您报告/记录该消息时,您已经开始捕获95%的有用信息。如果what()消息包含__ FILE __,__ LINE __和__ func __信息,那么您将获得大多数抛出异常提供的98%的重要信息。

即使没有仔细记录每个可以从每个特定函数调用抛出的异常类型的库,一个像样的库将提供用于抛出所有异常的基类型(通常它将是std ::异常或从中衍生出来的东西)。此异常基类将有一些获取相关错误消息的方法(例如what()调用)。

但是,即使您使用catch(...)作为最后一道防线,您的错误消息仍然可以指示命令失败以及它是什么命令。并且您有信心处理可能引发的每个异常。