D语言中的错误处理

原创 2005年03月02日 20:36:00

D中的错误处理

所有的程序都要应付错误。错误是不在程序正常操作范围内的异常情况:

  • 内存耗尽
  • 磁盘空间耗尽
  • 文件名无效
  • 试图写只读文件
  • 试图读不存在的文件
  • 请求不支持的系统服务

错误处理问题

C 语言检测报告错误的传统方法并没形成传统,每个函数都有自己的方法,包括:

  • 返回 NULL 指针。
  • 返回 0 值。
  • 返回非零的错误代码。
  • 需要检查 errno(译注:错误代码,鉴于此缩写已约定俗成,以下不译)。
  • 如果上述检查失败了,需要调用一个函数。

为了处理可能出现的错误,必须为每个函数添加繁琐的错误处理代码。如果发生了错误,必须有错误恢复代码,并且需要有代码将错误以某种友好的方式告诉给用户。如果不能在发生错误的局部环境处理错误,就必须显式地将错误传播给它的调用者。如果要显示错误类型,需要将一大堆 errno 值转换为合适的文字。这些代码可能占用整个项目编码时间的一大部分,而且如果运行时系统加入了一个新的 errno 值,旧有的代码就不能显示有意义的信息。

功能良好的错误处理代码很容易将清晰而简洁的实现搞得一团糟。

更糟的是,功能良好的错误处理代码本身就很容易出错,还总是整个项目中测试最不充分的部分(因此充满错误),并且还总是被简单地省略。最终的结果就如同“蓝屏死机”那样,程序由于无法处理一些未预料到的错误而失败。

并不值得为 Quick&Dirty 程序编写错误处理代码,因此使用这类程序就好像使用没有锯罩的多功能台式电锯。

我们所需要的是如下的错误处理哲学和方法学:

  • 标准化——如果用法一致,它就更有用。
  • 就算程序员无法查出出现了什么错误,也要使程序以合适的方式终止。
  • 在无需改动旧代码的前提下就可以加入新的错误类型,从而重用旧的代码。
  • 不会由于粗心大意而忽略某些错误。
  • 使 Quick&Dirty 程序能够正确地处理错误。
  • 可以很容易地写出清晰的错误处理代码。

D 的错误处理解决方案

先让我们观察一下并对错误作出以下假设:

  • 错误不属于正常的程序流。错误是异常的、不常见的、不该出现的。
  • 因为错误不常见,所以错误处理代码的性能并不十分重要。
  • 程序的正常逻辑流的性能很关键。
  • 所有的错误必须采用统一的方式处理,不论是显式地编写代码处理它们还是采用系统默认的处理方式。
  • 相比于负责从错误中恢复的代码,负责检测错误的代码拥有更多关于错误的信息。

解决方案是使用异常处理来报告错误。所有的错误都是从抽象类 Error 派生的对象。Error 类有一个叫做 toString() 的纯虚函数,它返回一个 char[] 类型的人类可读的错误描述。

如果代码检测到了一个错误,如“内存耗尽”,则抛出 Error 对象,其中包含消息“内存耗尽”。函数调用堆栈会被展开,并查找 Error 的处理程序。随着堆栈的展开,相应的 finally 块会被执行。如果找到了错误处理程序,就在该处恢复程序的执行。否则,会运行默认的错误处理程序,该程序会显示错误消息并终止程序。

这个解决方案是否能满足我们的要求?

标准化——如果用法一致,它就更有用。
这正是 D 的方法,D 运行时库和示例都采用这种方式。
就算程序员无法查出出现了什么错误,也要使程序以合适的方式终止。
如果没有相应的错误处理程序,程序会执行默认的错误处理程序,该处理程序打印出适当的消息,并使程序优雅的推出。
在无需改动旧代码的前提下就可以加入新的错误类型,从而重用旧的代码。
旧的代码可以决定是捕获所有的错误,或者是只捕获特定的错误并向上传播剩余的错误。无论那种情况,都不必为每个错误代码关联一个消息了,编译器会自动为其提供正确的消息。
不会由于粗心大意而忽略某些错误。
异常会采用这种或那种方式处理。不会出现使用 NULL 指针表示出错,但后面的代码却试图使用该 NULL 指针的情况。
使 Quick&Dirty 程序能够正确地处理错误。
Quick&Dirty 代码根本不需要包含任何错误处理代码,也不需要检查错误。错误会被默认的处理程序捕获,显示适当的消息,然后程序会优雅的终止。
可以很容易地写出清晰的错误处理代码。
try/catch/finally 语句比那些无穷无尽的 if (出错) goto 处理程序; 语句要清晰得多。.

这个解决方案是否符合我们对于的错误的假设?

错误不属于正常的程序流。错误是异常的、不常见的、不该出现的。
D 的异常处理机制完全符合上述假定。
因为错误不常见,所以错误处理代码的性能并不十分重要。
异常处理堆栈的展开相对较慢。
程序的正常逻辑流的性能很关键。
因为正常的代码流不必检查每个函数调用的返回值是否代表出错,使用异常处理来处理错误确实会使程序运行得更快。
所有的错误必须采用统一的方式处理,不论是显式地编写代码处理它们还是采用系统默认的处理方式。
如果某个错误没有对应的处理程序,就会由运行时库中的默认处理程序处理。如果一个错误被忽略了,那一定是程序员特意添加了代码用于忽略这个错误,因此这一定是在程序员意料之中的。
相比于负责从错误中恢复的代码,负责检测错误的代码拥有更多关于错误的信息。
不需要将错误代码翻译为人类可读的字符串,错误检测代码而不是错误恢复代码负责生成正确的字符串。这种做法也使不同的程序出现相同的错误时会输出相同的消息。
版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

Linux C语言错误处理

中定义了perror(),perror是在标准输出上输出msg字符串,然后再后面加上:错误语段(这个错误语段对应这时的errno) 中定义了strerror(),strerror是把一个错误numb作...

C语言传统的错误处理方式setjmp与longjmp

setjmp和longjmp是C语言独有的,只有将它们结合起来使用,才能达到程序控制流有效转移的目的,按照程序员的预先设计的意图,去实现对程序中可能出现的异常进行集中处理。处理方式是:在调用setjm...

使用C语言访问MySQL数据 —— 连接和错误处理

2011-05-09 wcdj     可以通过许多不同的编程语言来访问MySQL,例如,C,C++,Java,Perl,Python,Tcl,PHP等。本文主要总结使用C语言接口如何访问MyS...

C语言错误处理

学习C++的时候就没有怎么重视异常这部分知识,后来知道也基本没有看到C++项目里面用try/catch的。google编程规范中甚至直接说明不使用C++这个特性,所以我一直都没搞明白这个“简单的”tr...

Go语言中的错误处理系统

Go语言中的错误处理系统原文链接:http://blog.csdn.net/cc7756789w/article/details/51014076 作者:牧歌 github:https://g...

Go语言错误处理

Go语言错误处理 十月 30, 2015 7 条评论 ...

【异常/错误处理系列】C语言如何实现异常处理

不管是哪门编程语言,在coding过程中,我们都会遇到一个很头痛的问题,就是如何处理函数的返回值和异常。函数返回值传统的处理的方法是使用If/else。但对于有返回码的函数,需要写“无数”的if分支,...

C语言的错误处理

为了开发强壮的程序,需要预见程序在执行时可能的错误,并对错误进行检测和处理以在错误发生时能够采取适当的行为。C语言提供了几个处理错误的函数库。断言C语言使用断言监控程序的行为,断言函数声明在中,原型为...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)