10.8 就崩溃吧?
减少与异常处理有关的复杂性的第四种技术是让应用程序崩溃。在大多数应用程序中,会有一些不值得尝试处理的错误。一般来说,这些错误很难或不可能处理,而且不经常发生。应对这些错误的最简单的方法是打印诊断信息,然后中止应用程序。
一个例子是在存储分配过程中发生的“内存不足”错误。考虑一下C语言中的malloc
函数,如果它不能分配到所需的内存块,就会返回NULL
。这是一个不幸的行为,因为它假定每个调用malloc
的人都会检查返回值,并在没有内存时采取适当的行动。应用程序包含对malloc
的多次调用,因此在每次调用后检查结果会增加很大的复杂性。如果程序员忘记了检查(这是很有可能的),那么如果内存耗尽,应用程序将会对一个空指针进行解引用,导致崩溃,从而掩盖了真正的问题。
此外,当应用程序发现内存耗尽时,它也无能为力。 原则上,应用程序可以寻找不需要的内存来释放,但如果应用程序有不需要的内存,它可能已经释放了它,这首先可以防止内存不足错误。 今天的系统有如此多的内存,内存几乎永远不会用完。 如果它耗尽了,则通常表明应用程序中存在错误。 因此,尝试处理内存不足错误几乎没有意义。 这会带来太多的复杂性而带来的好处太少。
一个更好的方法是定义一个新的方法ckalloc
,它调用malloc
,检查结果,如果内存耗尽,则带着错误信息中止应用程序。应用程序从不直接调用malloc
;它总是调用ckalloc
。
在更新的语言中,如C++和Java,如果内存用尽,new
操作符会抛出一个异常。捕捉这个异常的意义不大,因为异常处理程序很有可能也会尝试分配内存,这也会失败。动态分配的内存是任何现代应用程序的基本元素,如果内存耗尽,应用程序继续下去是没有意义的;最好是在检测到错误时立即崩溃。
还有许多其他错误的例子,在这些例子中,应用程序的崩溃是有意义的。对于大多数程序来说,如果在读或写一个打开的文件时发生I/O错误(如磁盘硬盘错误),或者如果一个网络套接字无法打开,应用程序没有什么可以恢复的,所以用一个明确的错误信息中止是一个明智的做法。这些错误并不频繁,所以它们不太可能影响应用程序的整体可用性。如果一个应用程序遇到内部错误,如不一致的数据结构,带着错误信息中止也是合适的。像这样的情况可能表明程序中存在错误。
在一个特定的错误中崩溃是否可以接受,取决于应用程序的情况。对于一个复制的存储系统来说,在一个I/O错误中中止是不合适的。相反,系统必须使用复制的数据来恢复任何丢失的信息。恢复机制将给程序带来相当大的复杂性,但恢复丢失的数据是系统为用户提供的价值的重要组成部分。
Last updated