手机站
网通分站
电信主站
密 码:
用户名:
当前位置 : 主页>程序设计>C/C++>列表

使用C 异常来取代exit()函数

来源:互联网 作者:west263.com 时间:2008-02-23
西部数码-全国虚拟主机10强!40余项虚拟主机管理功能,全国领先!双线多线虚拟主机南北访问畅通无阻!免费赠送企业邮局,.CN域名,自助建站480元起,免费试用7天,满意再付款! P4主机租用799元/月.月付免压金!
从C语言开始接触C 的人,恐怕都知道exit()这个函数,似乎现在很多的程式员都有这样一种习惯,在程式一碰到错误、或任务刚完成时,把调用exit()函数当成是一种最好的结束程式的方法。在以前遗留的许多老式C/C 代码中,这种现象很普遍,但当手头的软件项目逐步进展并越来越大时,就不得不面临合并以前分散的各个模块这项工作,此时,假如更有人记得起软件日志记录、错误宽容度、或至少适当的清理工作,就已是万幸了。本文中要说的方法,决不是一条设计准则,但是可减轻修正那些未良好设计及实现的老式代码时所带来的痛苦。

  用return来取代exit,无疑是解决此问题最显而易见的方法,假如软件项目很简单,这也是最高效的解决方案;然而,项目中经常有成打的函数分布在多个源文档中,且这些函数的调用也嵌套在很深的层次中,那么,事情就变得棘手了。假如在这种情况中,任何的函数都返回void,还是有可能修改他们,让其返回一个退出码(exit code)的,但所付出的代价也很大;假如函数已能返回一个有意义的值,只是在碰到错误时,调用了exit(),那么这项工作会变得更消耗时间,也会更加容易出错。这里说点题外话,使用exit()也是有可取之处的,当老式代码没有设计返回任何东西时,假如想得到返回码(return code),只有靠exit()了。

  有关此问题,还是有一个解决方法的,在这种情况下,我们假定任何的源代码已为C 格式,或无需全部编译就能够移植为C 格式,把任何exit出现的地方全部换成throw(这能够自动完成,甚至无须理解老代码是怎样工作的);接着,在任何适当的地方,捕获为整数的异常码,这种方法还可依据严重性或恢复程度的不同,在不同层面上处理错误。

  请看以下示例,原始代码如下:

// main.cpp
void main() {
 //初始化
 ...
 ProcessMail(...);
}

//另一个源文档
void ProcessMail(...) {
 //初始化
 ...
 if ( initializationError ) {
  printf("faild to init!!!\n");
  exit(-1);
 }
 while ( !shutdown ) {
  ReadMail(...)
  //继续处理
  ...
 }
}

void ReadMail(...)
{
 ...
 //对ReadBytes()的调用出现在函数内的多处地方,包括在循环中。
 nBytesAvailable = ReadBytes(...)
 ...
}

//另一个源文档
int ReadBytes(...)
{
 //读取数据
 ...
 if ( error ) {
  printf("there was an error!!\n");
  exit(-1);
 }
 return nBytesRead;
}
在原始代码中缺少恢复或日志记录的功能,假如发生了一个错误,程式就会"消失"不见了,让用户手足无措。下面是重新组织后的代码,注意,没有修改函数修饰符:

void main() {
 //初始化
 ...
 try {
  ProcessMail(...);
 } catch (int ret) {
  switch (ret) {
   case E_INITIALIZATION_FAILURE: ...
   case E_IRRECOVERABLE: ...
   ...
  }
 }
}

void ProcessMail(...) {
 //初始化
 ...
 if ( initializationError ) {
  throw(E_INITIALIZATION_FAILURE);
 }

 while ( !shutdown ) {
  try {
   ReadMail(...)
  } catch (int ret) {
   switch (ret) {
    case E_READ_ERROR:
     //记录错误信息
     ...
     //试图恢复
     ...
     if ( recovered ) {
      continue;
     } else {
      throw(E_IRRECOVERABLE);
     }
     break;
    case ...
   }
  }
  //继续处理
  ...
 }

 //throw()能够用来取代缺少的返回码
 //但也要注意由此带来的性能损失

 throw(S_OK);
} // ProcessMail()

void ReadMail(...)
{
 ...
 //在此无须捕获异常
 nBytesAvailable = ReadBytes(...)
 ...
}

int ReadBytes(...)
{
 //读取数据
 if ( error ) {
  throw(E_READ_ERROR);
 }
 return nBytesRead;
}



文章整理:西部数码--专业提供域名注册虚拟主机服务
http://www.west263.com
以上信息与文章正文是不可分割的一部分,如果您要转载本文章,请保留以上信息,谢谢!

热点关注
IDC资讯 虚拟主机 域名注册 托管租用 vps主机 智能建站
网站运营 建站经验 策划盈利 搜索优化 网站推广 免费资源
网站联盟 联盟新闻 联盟介绍 联盟点评 网赚技巧
行业资讯 业界动态 搜索引擎 网络游戏 门户动态 电子商务 广告传媒
网络编程 Asp.Net编程 Asp编程 Php编程 Xml编程 Access Mssql Mysql 其它
服务器技术 Web服务器 Ftp服务器 Mail服务器 Dns服务器 安全防护
软件技巧 其它软件 Word Excel Powerpoint Ghost Vista QQ空间 QQ FlashGet 迅雷 Internet Explorer
网页制作 FrontPages Dreamweaver Javascript css photoshop fireworks Flash
程序设计 Java技术 C/C++ VB delphi
网络知识 网络协议 网络安全 网络管理 组网方案 Cisco技术
操作系统 Win2000 WinXP Win2003 Mac OS Linux FreeBSD
返回首页 |关于我们 | 联系我们 | 付款方式 | 创业联盟 | 价格总览 | 资讯中心 | 友情链接 | 网站地图 | 招贤纳士 | RSS