网络知识 娱乐 VC++异常捕获__try...__except和try...catch的使用介绍(附源码)

VC++异常捕获__try...__except和try...catch的使用介绍(附源码)

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接口获取产生异常的原因。