VC++常用功能开发汇总(专栏文章列表,欢迎订阅,持续更新...)https://blog.csdn.net/chenlycly/article/details/124272585 在C/C++的代码中,为了防止代码块执行的过程中产生异常导致软件崩溃,我们会给代码块添加__try...__except或try...catch保护,防止软件因为操作内部触发的异常产生崩溃。本文简单地介绍一下这两种异常捕获的使用示例。
1、概述
当软件运行过程中代码抛出异常,如果异常没有处理,且异常不可自动恢复,会导致软件崩溃闪退。C/C++中提供了异常保护机制,可以捕获到异常并处理掉,这样软件不会因为一些操作的内部错误而产生崩溃,软件可以正常的运行下去。
C语言中提供了SEH结构化异常捕获__try...__except,C++中则在__try...__except基础上提供了C++版本的try...catch机制,使用try...catch可以捕获到代码抛出的多种类型的异常,比如捕获到抛出的异常类信息。
2、使用C版本的__try...__except捕获异常
C语言版本的__try...__except的声明如下:
__try
{
// guarded code
}
__except ( expression )
{
// exception handler code
}
我们在调用API函数HtmlHelp打开.chm帮助文档时,如果指定路径中的.chm文件不存在(可能是路径不对,也可能是文件被删除了),HtmlHelp函数内部会抛出异常,软件会发生崩溃。后来我们直接添加__try...__except去捕获异常,对调用HtmlHelp的代码添加保护,保证即使.chm文件不存在,也不能让软件发生崩溃,相关代码如下:
bool OpenChmHelpFile( LPCTSTR lpStrPath )
{
HWND hHelpWnd = NULL;
__try
{
hHelpWnd = HtmlHelp( NULL, lpStrPath, HH_DISPLAY_TOPIC, NULL );
}
__except( EXCEPTION_EXECUTE_HANDLER )
{
hHelpWnd = NULL;
}
if ( NULL == hHelpWnd )
{
WriteLog( _T("[OpenChmHelpFile] HtmlHelp execute failed, path [%s]!"), lpStrPath );
return false;
}
return true;
}
在上述代码中,在__except分支条件中直接设置EXCEPTION_EXECUTE_HANDLER,表示此处我们认领并处理这个异常,这样就不会因为异常未得到处理导致软件崩溃了。
3、使用C++版本的try...catch捕获异常
C++版本的try...catch的声明如下:
try {
// code that could throw an exception
}
[ catch (exception-declaration) {
// code that executes when exception-declaration is thrown
// in the try block
}
[catch (exception-declaration) {
// code that handles another exception type
} ] . . . ]
// The following syntax shows a throw expression:
throw [expression]
使用C++版本的try...catch去捕获异常,不仅能捕获到代码抛出的基本类型的异常,还能捕获到C++代码抛出的异常类。比如在进程内存不足时,我们去new一段内存时可能会返回失败,new内部会抛出异常,此时我们可以使用try...catch捕获到异常,并查看到产生异常的原因,相关代码如下:
#include
using namespace std;
int main(){
char *p;
int i = 0;
try
{
do{
p = new char[10*1024*1024];
i++;
Sleep(5);
}
while(p);
}
catch(const std::exception& e)
{
std::cout << e.what() << "n"
<< "分配了" << i*10 << "M" << std::endl;
}
return 0;
}
new抛出的是std::exception异常类,该异常类的定义如下:
D:Program Files (x86)Microsoft Visual Studio2017CommunityVCToolsMSVC14.16.27023includevcruntime_exception.h
namespace std {
#pragma warning(push)
#pragma warning(disable: 4577) // 'noexcept' used with no exception handling mode specified
class exception
{
public:
exception() noexcept
: _Data()
{
}
explicit exception(char const* const _Message) noexcept
: _Data()
{
__std_exception_data _InitData = { _Message, true };
__std_exception_copy(&_InitData, &_Data);
}
exception(char const* const _Message, int) noexcept
: _Data()
{
_Data._What = _Message;
}
exception(exception const& _Other) noexcept
: _Data()
{
__std_exception_copy(&_Other._Data, &_Data);
}
exception& operator=(exception const& _Other) noexcept
{
if (this == &_Other)
{
return *this;
}
__std_exception_destroy(&_Data);
__std_exception_copy(&_Other._Data, &_Data);
return *this;
}
virtual ~exception() noexcept
{
__std_exception_destroy(&_Data);
}
virtual char const* what() const
{
return _Data._What ? _Data._What : "Unknown exception";
}
private:
__std_exception_data _Data;
};
通过调用exception::What接口获取产生异常的原因。