C++中 异常处理的 实现方式

1、异常是什么?

  • 程序执行期间出现的错误或意外情况。

 

2、传统的异常处理方式

  • 条件判断、分支处理 if
    • 优点:实现简单直观
    • 缺点:a、种类及情况太多,在大型系统中很难全部考虑到,导致程序崩溃,终止运行

b、某些异常情况的发生具有随机性,无法在程序中做出明确的处理,但是我们有时候又希望程序能够跳过异常部分错误运行。

c、我们希望可以传递异常信息,也就是发生异常时,可以把异常信息发送到其他地方进行处理。

3C++中的异常机制

当程序中发生异常时,生成一个异常对象来记录异常信息,然后把该异常发送到异常处理程序。

抛出异常:可以通过throw关键字 throw new DivideZero()// 抛出一个除0 异常的临时对象。

捕获异常、处理异常:try{} catch(异常对象(*) {}

 

4、异常机制的使用:

想要在C++中使用异常,首先要自己定义异常,然后才能在特定情况下,通过throw 抛出异常。

java python 用过了感觉很不方便呀)

我们可以定义一个空的异常类, 也可以在异常类中添加成员,以获取调用层级关系,建议的解决方法等。

5、异常的处理方法

可以在抛出异常的地方直接处理,在可以明确异常信息的情况下使用。通常就是传送到使用的函数中进行处理。

示例代码:

class DivideZero // 定义异常类,和普通类的定义一样,可以采用继承等结构

{

public:

voidshow()

{

printf("dividezero");

}

 

};

 

classA

{

public:

voidfun(int x, int y)

{

if(0 == x)

{

throw new DivideZero(); // 抛出异常

}

printf("%d\n",x+y);

}

};

 

int_tmain(int argc, _TCHAR* argv[])

{

Aa;

 

try

{

a.fun(0,1);

}

catch (DivideZero * e) // 捕获异常

{

printf("error");

e->show();

 

}

return0;

}

通过把异常传递给函数的调用者来处理异常。

classA

{

public:

voidfun(int x, int y)

{

try{

if(0 == x)

{

thrownew DivideZero();

}

}

catch(DivideZero * pe)

{

pe->show();

}

 

printf("%d\n",x+y);

}

};

在抛出异常的地方直接处理。

 

6、编译器是如何对异常进行处理的?

涉及到一些运行库的内容,目前还不是很清楚,现在只从反汇编的角度做以下初步的解释。

fun 函数中的throw

if(0 == x)

01102D83 cmp         dword ptr [x],0   // 比较x 0的值

01102D87 jne         A::fun+9Eh(01102DFEh)   // 不相等的时候直接跳过

{

thrownew DivideZero();

01102D89  mov        dword ptr [ebp-0E0h],1 

01102D93  mov        eax,dword ptr [ebp-0E0h] 

01102D99  push       eax 

01102D9A call        operator new(0110141Fh)  // 生成异常对象,指针在eax

01102D9F  add        esp,4 

01102DA2  mov        dword ptr [ebp-0D4h],eax 

01102DA8  cmp        dword ptr [ebp-0D4h],0 

01102DAF  je         A::fun+77h (01102DD7h) 

01102DB1  mov        ecx,dword ptr [ebp-0E0h] 

01102DB7  push       ecx 

01102DB8  push       0 

01102DBA  mov        edx,dword ptr [ebp-0D4h] 

01102DC0  push       edx 

01102DC1  call       _memset (01101514h) 

01102DC6  add        esp,0Ch 

01102DC9  mov        eax,dword ptr [ebp-0D4h] 

01102DCF  mov        dword ptr [ebp-0F4h],eax 

01102DD5  jmp        A::fun+81h (01102DE1h) 

01102DD7  mov        dword ptr [ebp-0F4h],0 

01102DE1  mov        ecx,dword ptr [ebp-0F4h] 

01102DE7  mov        dword ptr [ebp-0ECh],ecx 

01102DED  push       110F824h 

01102DF2  lea        edx,[ebp-0ECh] 

01102DF8  push       edx 

01102DF9 call        __CxxThrowException@8(0110128Fh)   //调用运行库中的中断抛出函数

}

<<throw.cpp>>

附件中为ThrowException的解释。抛出异常由运行时库来进行,设计上类似于CPU的中断,都有一个中断码,在catch中由中断码来判断异常类型。

 

try

{

01109664  mov        dword ptr [ebp-4],0 

a.fun(0,1);

0110966B  push       1 

0110966D  push       0 

0110966F  lea        ecx,[a] 

01109672  call       A::fun (0110150Ah) 

}

01109677  jmp         wmain+7Eh (0110969Eh)   // 1

catch(DivideZero * e)

{

printf("error");

01109679  mov        esi,esp 

0110967B  push       110D9B8h 

01109680  call       dword ptr ds:[11111C0h] 

01109686  add        esp,4 

01109689  cmp        esi,esp 

0110968B  call       __RTC_CheckEsp (01101366h) 

e->show();

01109690  mov        ecx,dword ptr [ebp-28h] 

01109693  call       DivideZero::show (0110150Fh) 

 

}

01109698  mov        eax,11096A7h 

0110969D  ret 

0110969E  mov        dword ptr [ebp-4],0FFFFFFFFh 

011096A5  jmp        $LN7+7h (011096AEh) 

$LN7:

011096A7  mov        dword ptr [ebp-4],0FFFFFFFFh

在没有异常情况发生时, try的末尾会像if 一样添加一条跳转语句,跳转到catch 后面执行,如果发生异常,则根据运行库的异常初步处理结果中的Exception number 来判断进入哪一个catch 语句中执行。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值