动态网站制作指南 [  QQ表情  ]
[ 投票调查 ]
[ 企业邮箱 ]
[ 网站空间 ]
网络编程 | 站长之家 | 网页制作 | 图形图象 | 操作系统 | 冲浪宝典 | 软件教学 | 网络办公 | 邮件系统 | 网络安全 | 认证考试 | 系统进程
ASP源码 | .Net源码 | PHP源码 | JSP源码 | JAVA源码 | CGI源码 | VB源码 | C++源码 | Delphi源码 | PB源码 | VF源码 | 汇编 | 服务器
电脑书籍下载:程序设计书籍 | 数据库教程书籍 | 平面与多媒体书籍 | 网络通讯书籍 | 系统管理书籍 | 网络安全书籍 | 认证考试书籍
Firefox | IE | Maxthon | 迅雷 | 电驴 | BitComet | FlashGet | QQ | QQ空间 | Vista | 输入法 | Ghost | Word | Excel | wps | Powerpoint
asp | .net | php | jsp | Sql | c# | Ajax | xml | Dreamweaver | FrontPages | Javascript | css | photoshop | fireworks | Flash | Cad | Discuz!
当前位置 > 网站建设学院 > 网络编程 > C/C++教程
Tag:注入,存储过程,分页,安全,优化,xmlhttp,fso,jmail,application,session,防盗链,stream,无组件,组件,md5,乱码,缓存,加密,验证码,算法,cookies,ubb,正则表达式,水印,索引,日志,压缩,base64,url重写,上传,控件,Web.config,JDBC,函数,内存,PDF,迁移,结构,破解,编译,配置,进程,分词,IIS,Apache,Tomcat,phpmyadmin,Gzip,触发器,socket
网络编程:ASP教程,ASP.NET教程,PHP教程,JSP教程,C#教程,数据库,XML教程,Ajax,Java,Perl,Shell,VB教程,Delphi,C/C++教程,软件工程,J2EE/J2ME,移动开发
文章搜索服务
邮件订阅
输入你的邮件地址,
你将不会错过任何关于:
[ C/C++教程 ]的信息



本月文章推荐
.C/C++中字符串常量的不相等性及字.
.创建一个可调整大小和拖拽的Edit.
.websphere新建C/C++客户机.
.(02)数据结构题解-线性表.
.如何在快速启动栏创建快捷方式.
.轻轻松松从C一路走到C++系列文章.
.只要有可能就推迟变量定义.
.C++ Builder 在对象观.
.C语言入门之转移语句.
.拼图游戏.
.C语言编的MD5主程序.
..
.C++ 中园形三角形按钮的实现.
.VC连接SQL SERVER数据库.
.新手入门:C/C++中的结构体.
.COM组件接口继承的实现.
.多层结构连接方式选择的分析.
.有趣的分形学Mandlbrot集图形的一.
.C++开发常用工具“群英会”.
.交叉编译.

C++的错误和异常处理分析

发表日期:2008-3-8 |


何时使用异常?

  一个简单的回答是:“当异常的语义和性能要求都恰当的时候。”

  一个经常被提到的方法是这样问自己:“这是一个例外(或者意外的)情形吗?”这个方法貌似挺吸引人,但是通常只会导致错误答案。对一个人来说是“异常”的情形对另一个人却“正常”:当你真正仔细考虑这句话时,就发现无法作出区分,这句话根本帮不了你。究竟,假如你检查了某个错误条件,就意味着你认为它会发生,否则你的检查不过是垃圾代码。

  一个更合适的问法是:“这里需要栈展开吗?”由于异常处理实际上几乎都意味着比正常流程代码要慢,还应该问自己:“这里负担得起栈展开的代价吗?”比如,正在做的一个要花很长时间的计算,并且周期性地检测用户是否按下了取消键。抛出异常可以优雅地取消操作。另一方面,在这个计算的内部循环中抛出并捕捉处理异常可能就不恰当,这么做可能导致严重的性能下降。前述内容包含这样一个原则:对于时间要害的代码,抛出异常才是一种“异常”的做法,而不是常规.

  如何设计异常类?

  1. 从std::exception派生异常类。除了一些非常罕见的情况,例如负担不了需函数的开销。把std::exception作为异常基类是合理的,当它被广泛使用后,将答应程序员捕捉任何异常而不必使用catch(...).更多关于catch(...)的内容,请看后文。

  2. 使用虚拟继续。这个深刻的洞察力来自Andrew Koenig. 当抛出的一个异常是从多个基类派生,并且这些基类有共同的部分,catch点就会碰到歧义问题,从异常基类虚拟继续可以防止这种歧义问题:

#include <iostream>
strUCt my_exc1 : std::exception { char const* what() const throw(); };
struct my_exc2 : std::exception { char const* what() const throw(); };
struct your_exc3 : my_exc1, my_exc2 {};

int main()
{
try { throw your_exc3(); }
catch(std::exception const& e) {}
catch(...) { std::cout << "whoops!" << std::endl; }
}
  上面的程序将打印出“whoops” ,因为C++运行时刻无法决定用那个exception实例去匹配第一个catch.(秃子:我的建议是这里最好别使用多重继续)

  3. 不要内嵌std::string对象或者其他拷贝构造可能抛出异常的数据成员、基类。在上述点抛出异常将导致直接调用std::terminate().让基类或数据成员的默认构造函数可能抛出异常也是同样糟糕的主意,你本来是打算通过一个包含对象构造的throw表达式报告异常, 程序却无谓地中止了:

throw some_exception();

  当发生异常拷贝时,有几种方法避免复制字符串对象,例如在异常对象中嵌入一个定长存储区,或者通过引用计数来治理字符串。不过,在采用这些方法前,先考虑考虑下一条。

  4. 只在确实需要的时候才格式化what()返回的信息。格式化是一个典型的内存相关的操作,有可能抛出异常。最好把格式化推迟到栈展开之后,因为栈展开可能释放某些资源。对what()函数用catch(...)块加以保护是一个好主意,这样你就可以在格式化抛出异常时有了一个退路。

  5. 不要太在意what()的信息。在异常抛出点,对程序员来说,这是给出错误信息的好机会,但是你未必能够把相关信息组合成用户可以理解的形式。国际化就一个典型的情况。Peter Dimov给出了良好建议:建一个错误信息格式化的表格,把what()的字符串作为这个表的键。当标准库抛出异常时,假如我们只能获得其标准的what()字符串……

  6. 在异常类的public接口中暴露导致错误的有关信息。返回固定信息的what()意味着你忽视了暴露信息,而用户可能需要提供相关信息。例如,你的异常想报告数字范围错,报错的代码应该能够透过异常的公共接口让异常包含导致问题的那个变量值。假如你只是在what()中以文本方式表现这些数字,那些需要根据信息做更多(或更少)处理的程序员日子将很难过。

  7. 假如可能,让你的异常类对两次析构免疫。几款流行的编译器偶然会使异常对象被销毁两次。假如你能采取措施防御危害(比如,把释放的指针置零)就可以使代码更健壮。

  如何处理程序员犯错?

  作为开发者,假如我违反了所使用库的某个前条件,我不希望栈展开。我希望的是core dump或者等价物—一个能精确地在问题发生点检查程序状态的方法。这通常意味着assert()或者其他类似的东西。

  有时候为用户提供可以应付任意误用的强健的API是有必要的,但这样通常要付出不菲的代价。比如,一个常见需求是跟踪客户使用的每一个对象,从而可以验证合法性。假如你需要这种保护,通常是在一个简单API上再封装一层来实现。尽管你做得小心翼翼,有强健承诺的API也只能防御某些而不是所有会导致灾难的误用。客户也开始依靠那些保护并且所依靠的保护也将增长到接口保护不到的部分。

  windows开发者请注重:当你使用assert()时,大部分Windows编译器实际上都是抛出异常,并且被本地截获,这很不幸。事实上,截获的错误经常是段访问失败或者除零错。当你使用JIT(Just In Time)调试时这是个问题,这意味着在在唤醒调试器之前已经异常栈展开了,因为catch(…)将捕捉这个异常,其实这个并非C++异常。幸运的是,有一个鲜为人知的简单办法可以处理:

extern "C" void straight_to_debugger(unsigned int, EXCEPTION_POINTERS*)
{
throw;
}
extern "C" void (*old_translator)(unsigned, EXCEPTION_POINTERS*)= _set_se_translator(straight_to_debugger);
  这个方法无法应付在catch块中(或者catch块调用的函数中)抛出结构化异常的情况,但它确实可以解决绝大多数JIT导致的问题。

  该如何处理异常?

  压根就不处理异常一般是处理异常的最好办法。假如你让异常穿越你的代码,并且在析构函数中做清理工作,代码会更干净。

  尽可能避免catch(…)

  很不幸,其他非Windows操作系统一样会把非C++异常(例如线程中止)卷入到C++异常机制中去,而且,有时候也没有类似上面提到的_set_se_translator这样的hack手法加以解决。我们通常在析构函数或者catch块中做合理操作来维持系统的不变式,这通常是安全的。然而catch(...)也会捕捉非预期的系统通知,这时是不可能像对待普通C++异常一样来处理的,惯用的手法不再安全了。

  经过新闻组上长期的辩论之后,尽管不情愿,我还是得承认Hillel Y. Sims观点:除非所有操作系统修正前面的问题,否则,所有异常应该继续自std::exception,当所有人适应catch(std::exception&)而不是catch(...)时,世界将会更加美好。

  即使不考虑和操作系统间糟糕的交互情况,有时候,catch(...)仍然是最合适的选择。假如你根本不知道会有什么异常抛出,并且必须停止栈展开,这可能是你唯一出路。一个典型的情况就是跨语言的时候。

上一篇:奇技淫巧C++之懒惰计算 人气:242
下一篇:C++基本概念在编译器中的实现 人气:580
浏览全部C/C++的内容 Dreamweaver插件下载 常用网页广告代码全集
  最新网站源码 最新软件下载
2008-7-25 WikyBlog v1.7.0.1 多国语言版
2008-7-25 乐彼网上开店系统(56770 Eshop)
2008-7-25 赛特网站管理系统sitecms v3.6.0
2008-7-25 Modoer多功能点评系统 v1.0.1 Bu
2008-7-25 Shangducms Teamsuit! v1.1.0 开
2008-7-25 幻影动漫网视频系统(Ppdong) v1.
2008-7-25 acteecompany企业网站建设系统 v
2008-7-25 恒浪整合管理系统 ims v4.1 ACCE
2008-7-25 艺术图库系统 v1.0 beta
2008-7-19 UltraEdit 简体中文增强版 14.10
2008-7-19 CentOS 5.2 i386 LiveCD
2008-7-19 Snapture多功能相机 v1.4
2008-7-19 iAcces中文输入法 v1.0Build016
2008-7-19 Cookbook烹饪秘籍 v2.5
2008-7-19 苹果专用DVD转换工具 v1.1.59汉化
2008-7-19 Modem修复软件ZiPhone修改版04.0
2008-7-19 AgileMessenger即时通讯工具美化
2008-7-19 Sketches画图软件 v0.7b6破解版


  发表评论
姓 名: 验证码:
内 容:
[ 汉字翻译拼音 ] [ 广告代码 ] [ 符号对照表 ] [ 进制转换 ] [ 经典小工具 ] [ 个税计算 ] [ 汉字简繁转换 ] [ 普通单位换算 ] [ 公制单位换算 ]
[ 生辰老黄历 ] [ 国内电话区号 ] [ 国家代码与域名缩写 ] [ 文字加密解密 ] [ 健康查询 ] [ 万年历 ] [ 手机号码查询 ] [ ip搜索 ] [ Google PR查询 ]
业务联系 | 广告刊登 | 频道合作 | 投稿荐稿 | 联系方式 | 加入收藏 | RSS订阅
Copyright © 2000-2008 www.knowsky.com All rights reserved | 网络实名:动态网站制作指南 | 沪ICP备05001343号