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

Posted dvlinker

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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 <iostream>
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 Studio\\2017\\Community\\VC\\Tools\\MSVC\\14.16.27023\\include\\vcruntime_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接口获取产生异常的原因。

以上是关于VC++异常捕获__try...__except和try...catch的使用介绍(附源码)的主要内容,如果未能解决你的问题,请参考以下文章

测试 __try, __finally, __except(被__finally捕获的异常, 还会被上一级的__except捕获。反之不行)

_14python基础_异常处理

python学习_26(异常)

人生苦短_我用Python_Try_Exception异常捕捉_007

MFC 日志捕获保存堆栈到日志文件

MFC 日志捕获保存堆栈到日志文件