选择显示字体大小

学习用于异常处理的terminate()函数

xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /> 


异常处理是一个微妙的问题,你应该尽可能优雅地处理所有异常。要达到这个目的,你需要学习terminate()函数。

terminate()函数在程序抛出一个异常并且异常没有被捕获的时候被调用,像下面这样:

#include
#include

void on_terminate()
{
std::cout << "terminate() 函数被调用了!" << std::endl;
std::cin.get();
}

int main()
{
// 如果用 vc6,去掉“std::”前缀
std::set_terminate( on_terminate);
throw std::exception();
std::cout << "terminate() 函数没有被调用!" << std::endl;
std::cin.get();
return 0;
}

避免这种情形的方案一开始看起来很简单:

int main()
{
try
{
/* code */
}
catch( std::exception & exc)
{
// 记录到日志,或作其他处理
}
catch(...)
{
// 记录下“unknown exception”
}
return 0;
}

不过,在多线程应用程序中情况变得有点复杂,因为你创建的每个线程都要有上面的(catch)处理过程。

然而terminate()函数在许多其它情况下会被调用,包括:

当你抛出一个异常,并且在它的拷贝构造函数中,另一个异常被抛出。
在堆栈展开的过程中抛出一个异常,此时析构函数抛出一个异常。
当一个静态对象的构造函数或析构函数抛出异常时。
当一个用atexit注册过的函数抛出一个异常时。
当你在代码中写下“throw;”(这意味着重新抛出当前异常),然而并没有当前异常时。
当一个函数抛出一个它的异常说明不允许的异常时
当默认的unexpected()处理过程被调用时
下面的代码演示了上面各种情况下的结果:

#include
#include

void on_terminate()
{ std::cout << "terminate()函数被调用了!" << std::endl;
std::cin.get(); }

//////////////////////////////// [1]
struct custom_exception
{
custom_exception() {}
custom_exception( const custom_exception &)
{ throw std::exception(); }
};

void case_1()
{
try
{ throw custom_exception(); }
catch(...)
{}
}

//////////////////////////////// [2]
struct throw_in_destructor
{
~throw_in_destructor() { throw std::exception(); }
};
void case_2()
{
try
{
throw_in_destructor temp;
throw std::exception();
}
catch(...)
{}
}

//////////////////////////////// [3]
struct static_that_throws
{
static_that_throws() { throw std::exception(); }
};

void case_3()
{
// 注意:用try/catch块包围下面的代码并不起作用
static static_that_throws obj;
}

//////////////////////////////// [4]
void throw_at_exit()
{ throw std::exception(); }

void case_4()
{ atexit( throw_at_exit); }

//////////////////////////////// [5]
void case_5()
{ throw; }

//////////////////////////////// [6]
class custom_6_a {};
class custom_6_b {};

void func_violating_exception_specification_6() throw(std::exception)
{ throw custom_6_a(); }

// 注意:按照我们的例子,在这个函数中我们只应该抛出
// std::exception(在函数func_violating_exception_specification
// 的定义中说明的异常);但我们没有这样做,
// 因此,terminate() 被调用
void on_unexpected()
{ throw custom_6_b(); }

void case_6()
{
std::set_unexpected( on_unexpected);
try
{ func_violating_exception_specification_6(); }
catch(...)
{}
}

//////////////////////////////// [7]
class custom_7 {};

void func_violating_exception_specification_7() throw(std::exception)
{ throw custom_7(); }

void case_7()
{
try
{ func_violating_exception_specification_7(); }
catch(...)
{}
}

int main()
{
std::set_terminate( on_terminate);
// 注意:确保每次仅去掉下面一个调用的注释,
// 以便分析时将每种情况隔离开来
case_1();
// case_2();
// case_3();
// case_4();
// case_5();
// case_6();
// case_7();
return 0;
}
尽管你应该努力避免terminate()函数会被调用的情况,我们还是建议你创建自己的terminate()处理过程。你的处理过程要做的唯一合理的事是记录一条消息到日志中。不管怎样,确保你的日志不会抛出任何异常。
std::ostream& get_log() { /* code */ }

void on_terminate()
{
std::ostream & log = get_log();
// 确保我们不会抛出任何东西!
try
{
log.exceptions( std::ios_base::goodbit);
}
catch (...)
{}
log << "terminate() 被调用了!" << std::endl;
}

int main()
{
std::set_terminate( on_terminate) ;
// . . .
}



 


关键字 本文所属关键字

相关 与本文相关文章

分类 所有文章关键字导航

源码编程相关

Java   Asp   PHP   .Net   XML   C/C++   CGI   VB   Jsp   J2ee   J2se   J2me   EJB   Servlet   Tomcat   Resin   Struts   Weblogic   Eclipse   ANT   GUI   JMS   Web servise   IDEA   Webphere   Hibernate   Spring   Jboss   Applet   Swing   Socket   Javamail   Perl   Ajax   P2P   安全   模式   框架   测试   开源   游戏

SQL数据库相关

My-SQL   Ms-SQL   Access   DB2   Oracle   Sybase   SQLserver   索引   存储过程   加密   数据库   分页   视图  

手机无线相关

3G   Wap   CDMA   GRPS   GSM   IVR   彩信   短信   无线   增值业务

网页设计制作相关

HTML   CSS   网页配色   网页特效   Javascript   VBscript   Dreamweaver   Frontpage   JS   Web   网站设计

网站建设推广相关

建站经验   网站优化   网站排名   推广   Alexa

操作系统/服务器相关

Windows XP   Windows 2000   Windows 2003   Windows Me   Windows 9.x   Linux   UNIX   注册表   操作系统   服务器   应用服务器

图形图像多媒体相关

Photoshop   Fireworks   Flash   Coreldraw   Illustrator   Freehand   Photoimpact   多媒体   图形图像

标准 网站致力的规范

Valid CSS!

无不良内容,无不良广告,无恶意代码

Valid XHTML 1.0 Transitional

creativecommons