`
hqs7636
  • 浏览: 221022 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

D 中的错误处理 2.014

阅读更多
无版本差异


我来了,我编码了,我崩溃了。-- Julius C'ster
所有的程序都要应付错误。错误是不在程序正常操作范围内的异常情况:常见的错误情况
有:
• 内存耗尽。
• 磁盘空间耗尽。
• 文件名无效。
• 试图写只读文件。
• 试图读不存在的文件。
• 请求不支持的系统服务。
21.1 错误处理问题
C 语言检测报告错误的传统方法并没形成传统,每个函数都有自己的方法,包括:
• 返回 NULL 指针。
• 返回 0 值。
• 返回非零的错误代码。
• 需要检查 errno。
• 如果上述检查失败了,需要调用一个函数。
为了处理可能出现的错误,必须为每个函数添加繁琐的错误处理代码。如果发生了错误,必
须有错误恢复代码,并且需要有代码将错误以某种友好的方式告诉给用户。如果不能在发生
错误的局部环境处理错误,就必须显式地将错误传播给它的调用者。如果要显示错误类型,
需要将一大堆 errno 值转换为合适的文字。这些代码可能占用整个项目编码时间的一大部
分,而且如果运行时系统加入了一个新的 errno 值,旧有的代码就不能显示有意义的信息。
功能良好的错误处理代码很容易将清晰而简洁的实现搞得一团糟。
更糟的是,功能良好的错误处理代码本身就很容易出错,还总是整个项目中测试最不充分的
部分(因此充满错误),并且还总是被简单地省略。最终的结果就如同“蓝屏死机”那样,
程序由于无法处理一些未预料到的错误而失败。
并不值得为“快速而脏的(quick and dirty)”程序编写错误处理代码,因此使用这类程序就好
像使用没有锯罩的多功能台式电锯。
我们所需要的是如下的错误处理哲学和方法学:
• 标准化——如果用法一致,它就更有用。
• 就算程序员无法查出出现了什么错误,也要使程序以合适的方式终止。
• 在无需改动旧代码的前提下就可以加入新的错误类型,从而重用旧的代码。
• 不会由于粗心大意而忽略某些错误。
• 重写“快速而脏的”程序直到能够正确处理错误。
• 可以很容易地写出清晰的错误处理代码。
197
第 21 章 D 中的错误处理 — 张雪平
21.2 D 的错误处理解决方案
先让我们观察一下并对错误作出以下假设:
• 错误不属于正常的程序流。错误是异常的、不常见的、不该出现的。
• 因为错误不常见,所以错误处理代码的性能并不十分重要。
• 程序的正常逻辑流的性能很关键。
• 所有的错误必须采用统一的方式处理,不论是显式地编写代码处理它们还是采用系统
默认的处理方式。
• 相比于必须从错误里进行恢复的代码,负责检测错误的代码了解更多关于错误的信
息。
解决方案是使用异常处理来报告错误。所有的错误都是从抽象类 Error 派生的对象。Error
类有一个叫做 toString() 的纯虚函数,它返回一个 char[] 类型的人类可读的错误描述。
如果代码检测到了一个错误,如“内存耗尽”,则抛出 Error 对象,其中包含消息“内存耗
尽”。函数调用堆栈会被展开,并查找 Error 的处理程序。随着堆栈的展开,相应的
Finally 块 会被执行。如果找到了错误处理程序,就在该处恢复程序的执行。否则,会运行
默认的错误处理程序,该程序会显示错误消息并终止程序。
这个解决方案是否能满足我们的要求?
标准化——如果用法一致,它就更有用。
这正是 D 的方法,D 运行时库和示例都采用这种方式。
就算程序员无法查出出现了什么错误,也要使程序以合适的方式终止。
如果没有相应的错误处理程序,程序会执行默认的错误处理程序,该处理程序打印出
适当的消息,并使程序优雅的推出。
在无需改动旧代码的前提下就可以加入新的错误类型,从而重用旧的代码。
旧的代码可以决定是捕获所有的错误,或者是只捕获特定的错误并向上传播剩余的错
误。无论那种情况,都不必为每个错误代码关联一个消息了,编译器会自动为其提供
正确的消息。
不会由于粗心大意而忽略某些错误。
异常会采用这种或那种方式处理。不会出现使用 NULL 指针表示出错,但后面的代码
却试图使用该 NULL 指针的情况。
重写“快速而脏的”程序直到能够正确处理错误。
“快速而脏的”代码根本不需要包含任何错误处理代码,也不需要检查错误。错误会
被默认的处理程序捕获,显示适当的消息,然后程序会优雅的终止。
可以很容易地写出清晰的错误处理代码。
try/catch/finally 语句比那些无穷无尽的 if (出错) goto 处理程序; 语句要清晰得多。
这个解决方案是否符合我们对于的错误的假设?
错误不属于正常的程序流。错误是异常的、不常见的、不该出现的。
D 的异常处理机制完全符合上述假定。
因为错误不常见,所以错误处理代码的性能并不十分重要。
异常处理堆栈的展开相对较慢。
198
第 21 章 D 中的错误处理
程序的正常逻辑流的性能很关键。
因为正常的代码流不必检查每个函数调用的返回值是否代表出错,使用异常处理来处
理错误确实会使程序运行得更快。
所有的错误必须采用统一的方式处理,不论是显式地编写代码处理它们还是采用系统默认的
处理方式。
如果某个错误没有对应的处理程序,就会由运行时库中的默认处理程序处理。如果一
个错误被忽略了,那一定是程序员特意添加了代码用于忽略这个错误,因此这一定是
在程序员意料之中的。
相比于必须从错误里进行恢复的代码,负责检测错误的代码了解更多关于错误的信息。
不需要将错误代码翻译为人类可读的字符串,错误检测代码而不是错误恢复代码负责
生成正确的字符串。这种做法也使不同的程序出现相同的错误时会输出相同的消息。
使用异常来处理错误会导致其它的问题——如何写出异常安全的程序。这里有关于怎么做的
说明。
分享到:
评论

相关推荐

    R7F0C014B2D.pdf

    根据提供的文件信息,我们可以得出这份文档是关于R7F0C014B2D与R7F0C014L2D型号单片机的用户手册硬件篇。接下来,我们将从标题、描述以及部分展示的内容中提取关键知识点。 ### 关键知识点一:R7F0C014B2D与R7F0C...

    AT45DB014D的中文资料及程序

    2. 示例代码:可能是用C或汇编语言编写的,展示了如何控制AT45DB014D进行读写操作,对初学者尤其有帮助。 3. 应用笔记或教程:解释了如何将AT45DB014D集成到实际项目中,可能包括硬件连接指南和软件实现步骤。 4. ...

    程序员-3期(PX014) 初级程序员2009年下半年上午试题答案.doc

    4. 错误和异常处理:A C C D 可能涉及错误类型、异常捕获和处理机制。 5. 面向对象编程:A B A B 这部分可能包括类的定义、对象的创建、继承、封装和多态性等概念。 6. 操作系统原理:D C C D 可能考察了进程管理...

    2012-2013学年度上期期末测试题.pdf

    2. 数学等式解析:在内容中,“D.2x3y=1”可能表示一个关于x和y的二元一次方程。此外,“x21=3”和“y2y=0”可能是某种特定条件下的代数表达式。 3. 分数和小数的表示:内容中出现“0.25abba=014”可能意在表达分数...

    程序员-3期(PX014) 初级程序员2010年下半年下午试题答案.doc

    2. **条件判断**: - `len>1` 是一个简单的比较语句,检查变量`len`是否大于1。 3. **C语言编程**: - 错误修复,如在第19行,原始代码可能没有正确地为数组元素赋值,改正后使用了`fscanf(fp,”%d”,&arr[num++]...

    程序员-3期(PX014) 初级程序员2010上半年下午试题答案.doc

    综合来看,这些试题旨在测试考生对基础编程概念、数据结构、控制流程、错误处理等方面的知识掌握情况,对于准备初级程序员考试的人员来说,这些都是必备的技能点。通过解答这些问题,考生可以巩固和提高他们在编程...

    某装饰公司工作流程教材.pptx

    2. **设计与签单流程**: - 合同签定流程(B001):涉及设计师、业务员的工作流程,确保合同的合规签订。 3. **施工管理流程**: - **C001 派工流程**:指派施工队伍,分配工作任务。 - **C002 工程准备流程**:...

    数据库参考教程-数据库设计规范4net.xlsx

    2.英文名称规范:以名称复数命名",, S002,表注释,"1.在PD中的"Table Properties"-"General"中的Comment中填写表的注释。 2.注释规范: 作者:<姓名> 创建时间:<表的创建时间> 描述:<说明表的含义、用途以及设计...

    C语言指针的题目用来训练

    2. 赋值语句的正确性: - 在C语言中,指针可以被赋值为其他指针的值(C选项),但不能将整型变量的值赋给指针(B选项),也不能将指针赋值给整型变量(如ptr2=k)。选项A和D是正确的赋值方式。 3. 正确的指针操作...

    java手机归属地

    2. **构建URL**: - 根据输入的手机号码构建用于查询的URL。 3. **创建网络连接**: - 使用`URLConnection`类建立与目标网站的连接。 4. **获取并解析页面内容**: - 通过输入流读取网页内容,并将其转换为字符...

    LINUX与UNIX SHELL编程指南1

    2. **Shell输入与输出**(005-shell输入与输出.pdf): Shell允许重定向输入和输出,例如使用`>`和`操作符。`>`用于重定向输出到文件,`则将文件内容作为命令的输入。管道`|`可以连接多个命令,将一个命令的输出...

    迅达300P故障代码

    ##### 2. 003 NoKSE_STDSTL **故障描述**:位置传感器KSE故障。 - **可能原因**: - KSE位置及参数不符合要求。 - 磁铁的极性不正确。 - KSE开关及其到PCB的电缆有问题。 - **解决方法**: - 检查SHAFT_PARA.KSE...

    Card Technology Secure Channel Protocol '03' Card Specification v2.2

    最后,在“SecureChannelProtocolUsage”部分,文档将详细说明如何使用SCP03协议建立安全通道,可能包括通信过程中的密钥管理、会话建立、数据传输、错误处理和会话终止等步骤。 需要注意的是,由于文档内容的不...

    Android实现网络图片浏览器

    以上代码实现了基本的网络图片浏览器功能,但实际项目中可能需要考虑更多因素,如错误处理、图片缓存、内存管理等。例如,你可以使用`Glide`或`Picasso`这样的库来更高效地加载和管理网络图片,它们会自动处理内存...

    ASCII表[参考使用,居家必备]

    2. **SOH (Start of Header)**:报头开始标志。 3. **STX (Start of Text)**:文本开始标志。 4. **ETX (End of Text)**:文本结束标志。 5. **EOT (End of Transmission)**:传输结束标志。 6. **ENQ (Enquiry)**:...

    ASCII码简介对照表

    2. **标题开始(SOH)** - 十进制:1 - 八进制:001 - 十六进制:01 - 二进制:00000001 - HTML实体:`` - 描述:用于标识消息的标题部分的开始。 3. **正文开始(STX)** - 十进制:2 - 八进制:002...

    PHP中生成UUID自定义函数分享

    在 PHP 中,UUID(通用唯一...在实际项目中,可以根据具体需求进行优化或扩展,例如添加错误处理、性能优化等。同时,也可以考虑使用第三方库,如`ramsey/uuid`,它提供了更全面的UUID支持,包括不同版本和算法的生成。

Global site tag (gtag.js) - Google Analytics