当前位置导航:炫浪网>>网络学院>>编程开发>>C++教程>>C++进阶与实例

深入浅出话异常

标准C的处理机制

  标准C提供了几个异常管理机制,这些在标准C++也可用,虽然相关的头文件名有了改变:旧的C标准头文件名从<name.h>映射到新的C++标准头文件名<cname>。(头文件名的前缀C是为了记忆,指明它们是标准C的库文件)

  虽然在C++的向后兼容里保留了C的头文件,但我劝告你在任何可能的地方使用新的头文件。对于许多实际使用中,最大的改变是在新的头文件与namespace std内进行声明。请看以下示例:

#include <stdio.h>//在标准C里被替换成#include <cstdio>

FILE *f = fopen("blarney.txt", "r");

std::FILE *f = std::fopen("blarney.txt", "r");//or the more C-esque

#include <cstdio>
using namespace std;

FILE *f = fopen("blarney.txt", "r");
  不幸的是,Microsoft's Visual C++不能在新的头文件与namespace std同时具备的条件下进行声明,即使这种行为是标准C必需的。除非等到Visual C++支持这种行为,我将在本行使用旧的C风格名字。

  (对于像Microsft的库供应商来说,实现这些C库头文件的正确性需要维护与测试两套不同的代码,这是一项艰苦的任务,且不会带来任何价值)

  绝对终止

  这是一种彻底忽略异常的方法,大概这种简单的响应是一种安全的退出方法。在一些情形里,这是最正确的方法。

Before you scoff, consider that some exceptions betray a condition so severe that reasonable recovery is unlikely anyway. Perhaps the best example is malloc of a small object returning NULL. If the free store manager can't scrape together a few spare contiguous bytes, your program's robustness is severely compromised, and the odds of elegant recovery are slim.
  C库头文件<stdlib.h>提供了两个不是相当完美的程序函数:abort与exit,这些函数实现了异常的生命期在第4、5阶段。两者不返回它的调用者,并且结束程序。

  虽然两者在概念上是相关的,但使用它们的结果是不同的:

  abort: 粗鲁地结束程序。这是默认的,在运行时诊断里调用abort来安全结束程序。这种结束方式可能会或可能不会刷新与关闭打开的文件或删除临时文件,这与你的设计有关。 exit:文明地结束程序。它附加了关闭打开的文件与返回状态码给执行环境,exit还调用你用atexit注册的回调函数。
你通常是在发生程序重大失败的情况下调用abort,原因abort默认行为是立即结束程序,你需要在调用abort之前保存你的数据。(在讨论<signal.h>里会再提到)

  对于两者的差异,exit执行客户用atexit注册的清除代码,它们的调用顺序是按它们被注册的相反顺序来的。示例:

#include <stdio.h>
#include <stdlib.h>

static void atexit_handler_1(void)
{
printf("within 'atexit_handler_1'\n");
}

static void atexit_handler_2(void)
{
printf("within 'atexit_handler_2'\n");
}

int main(void)
{
atexit(atexit_handler_1);
atexit(atexit_handler_2);
exit(EXIT_SUCCESS);
printf("this line should never appear\n");
return 0;
}

/* When run yields
within 'atexit_handler_2'
within 'atexit_handler_1'

and returns a success code to calling environment.
*/
(注意:如果你的程序在main函数结束时没有显式调用exit,那么你用atexit注册的处理函数也会被调用)。

abort与exit都不将控制权返回给调用者,并且结束程序。 条件结束
abort与exit无条件终止你的程序。你也可以有条件地结束你的程序,这种机制是每一个程序员喜受的诊断工具:assert宏定义在<assert.h>,如下示例:

#if defined NDEBUG
#define assert(condition) ((void) 0)
#else
#define assert(condition) _assert((condition), #condition, __FILE__, __LINE__)
#endif
//*******************************************************//

(译注:assert的实现并不唯一,比如:

Visual C++ 6.0的实现是:

#define assert(eXP) (void)((exp)(_assert(#exp, __FILE__, __LINE__), 0));

Borland C++ 5.5的实现是:

#define assert(exp) ((exp) ? (void)0 : _assert(#exp, __FILE__, __LINE__))
  至于函数_assert(在gcc的库中_assert是一个宏)是各家的内部实现,不一定得非要_assert这个名字,其内容一般是利用printf函数(在WIN平台上往往是调用MessageBox)输出出错信息(文件名及行号)并调用abort终止程序。

  //*******************************************************//

  在这个定义里,当定义了预处理符号NDEBUG的时候,断言是无效的,这意味着assert断言宏只在你的Debug版本中有效。在Release版本里,assert断言宏不进行任何计算。由于这个而会引起一些侧面效里,比如:

共4页 首页 上一页 1 2 3 4 下一页 尾页 跳转到
相关内容
赞助商链接