对C++异常处理的讨论

源自CSDN讨论贴:http://topic.csdn.net/t/20060525/10/4777451.html

 

楼主cuipy(崔鹏宇) 2006-05-25 10:51:58 在 C/C++ / C++ 语言 提问

    我用try{正常代码执行}catch(...){处理},来处理异常,但为什么到出错的地方还是出错呢?   
    我看了资料说要在异常发生的时候自己抛出,那我要知道那里出现异常,我还不解决了丫?感觉不靠谱,望指教这个异常到底怎么处理。

1 楼goodluckyxl(被人遗忘的狗)回复于 2006-05-25 11:02:58 得分 0

    系统能捕捉的异常只有几个   
    异常处理机制还是在某些可能发生异常的情况下   
    处理异常流程抛出异常   来改变执行分支   
    并且error并不是异常     
    并不是说catch一下都能得到异常

2 楼cuipy(崔鹏宇)回复于 2006-05-25 11:07:11 得分 0

    这个我也感觉到了。看来跟java、c#可不太一样。那么如果你写一个程序,大型的。为了保证程序稳定运行,不挂。你就需要自己写一个异常类,然后在会出现异常的部分自己抛出?或者你有更优的解决方法?

3 楼kingbo2006(韫知)回复于 2006-05-25 11:15:11 得分 0

    在C++   中使用异常处理,一般情况下是在你让为可能出现错误的方,用try块将其包含在其中,以便捕获异常。但是也不能在程序设计中过度的使用异常处理。下面是一些不使用异常的原则:  
  1、不要在异步事件中使用异常。  
  2、不要在处理简单错误的时候使用异常。  
  3、不要将异常用于程序的流程控制。  
  4、不要强迫自己使用异常。  
  当我希望你把你代码贴一部分出来,让家看一看你问题出在哪里,这样会更加清楚一点,也有利于问题的解决。

4 楼cuipy(崔鹏宇)回复于 2006-05-25 11:18:53 得分 0

    这个代码可就比较麻烦了。因为我是在读一个大的程序。其中有不少地方会出现错误。我就打算用try   catch来作处理。没想到是这样的,我以前没有正经使用过c++。那我还得读程序。

    我能够找到代码在哪里出现问题的。但就是不太清楚原因。

5 楼goodluckyxl(被人遗忘的狗)回复于 2006-05-25 11:21:30 得分 0

    我还是习惯于使用c语言的return   返回错误信息   
    统一判断执行异常     
    而不使用try   catch

6 楼sharpdew(风刃)回复于 2006-05-25 11:36:09 得分 0

    为了保证系统在执行的时候不down掉,异常处理还是很需要的,比如说内存访问指针转化类型强制转化等你都不可能预料到是否会出现异常,这个时候就需要用try捕获,也许你可能在catch后不知道怎么处理异常,但是至少你要记录下这种异常发生地点,写入日志,以便将来系统的更新和维护。   
    C++并没有强调异常处理,但是作为写程序的人还是要特别关注C++可能导致异常的操作,至于由于程序设计中的逻辑错误,就是设计者本身的问题,系统基本上难以捕获。   
    设计一个统一的异常处理机制往往会有效率上的损失,这也是C++为啥把这个任务留给用户来取舍的原因。

7 楼lddLinan(不再五行中)回复于 2006-05-25 14:03:03 得分 0

1、不要在异步事件中使用异常。  
  ============================  
              何解?这和“异常机制不直接处理异步事件”是一样的么?  
   
  关于异常的advice,我来小小翻译一下:  
  1。使用异常作为“出错”处理  
  2。如果local的控制流本身就可以处理,那就不要使用异常,因为异常是处理不同单元之间消息传递的机制。  
  3。在使用异常的代码中,使用“资源分配即初始化”的技术来管理资源。比如将资源申请放入某个代理类的初始化中,将资源释放放入代理类的析构中,然后用这个代理来管理资源  
  4。不是所有的程序都需要是异常安全的。资源可以不被主动释放,比如你可以放心的将内存资源的释放交给操作系统(通过abort等)  
  5。可以使用“资源分配即初始化”的技术和异常处理来保持不变性。比如:保证异常发生前后环境不变,对于local变量可以通过代理释放资源,对于local以外的变量可以在catch后的异常处理中将内容恢复。  
  6。最小化try块的使用(能不用就不用)。不要在异常处理中释放资源,应使用“资源分配即初始化”的技术。  
  7。不是每个函数都需要处理所有的错误。  
  8。在构造函数中,抛出异常来暗示资源分配失败。这比构造函数设置一种失败的状态要好得多,清晰的多。  
  9。除非已经出现不可恢复的问题,不要在拷贝构造函数中抛出异常。因为拷贝构造函数通常涉及到两个操作:释放默认资源,获取新的资源。如果抛出异常,就很难恢复到拷贝构造前的状态。  
  10。不要在析构函数中抛出异常  
  11。在Main()函数中扑获所有异常  
  12。普通的代码和异常处理的代码不要耦合在一起。  
  13。确保构造函数获取的资源在析构函数里被释放  
  14。保持资源管理的结构层次。即不同层次的资源的获取和释放不要相互干涉。  
  15。使用”异常规范“作为主要的接口。即将模块的异常规范以接口的形式提供给模块的使用者,这也可以提高异常处理的效率和命中率。  
  16。要意识到,由new分配的内存不会在异常处理中释放掉。  
  17。如果一个程序可能抛出异常也可能不抛出,在使用这个程序时,最好是假设他会抛出异常(必要在不同模块之间产生不必要的耦合关系)  
  18。不是所有异常都继承自类exception  
  19。作为一个函数库,在出错的时候不应该一厢情愿的将程序关掉,而是应该通过抛出异常,将出错消息传达给他的使用者。异常正是在不同模块之间传递出错消息的很好的机制。  
  20。作为一个函数库,他不应该将出错诊断信息显示在IO设备上,比如stderr,他不应该对用户使用的设备作假定(或许,用户已经把stderr关掉了,或是根本就没有标准的显示终端),而应该是通过异常机制。  
  21。在设计阶段早期就安排好出错处理的策略。   

  《C++   Pragramming   Language》  
  如果有认识不妥的地方,大家一起来讨论一下。

8 楼cuipy(崔鹏宇)回复于 2006-05-25 14:08:09 得分 0

    我的这个代码比较大,我要是这么贴出来恐怕谁都不愿意理我了。

    谁能给我一个try   catch来防止程序当掉的例子?我在我的程序肯定出错的那个函数里面加了try,但根本就没有用。  
  try{  
   
          data.Initialize(MSG_PVP_LOG_DATA);                                             //   MSG_PVP_LOG_DATA  
          data   <<   uint8(0x0);  
          data   <<   uint32(sBattleGroundMgr.GetBattleGround(GetPlayer()->m_bgBattleGroundID)->GetPlayerScoresSize());      
   
          for(std::map<uint64,   BattleGroundScore>::iterator   itr=sBattleGroundMgr.GetBattleGround(GetPlayer()->m_bgBattleGroundID)->GetPlayerScoresBegin();itr!=sBattleGroundMgr.GetBattleGround(GetPlayer()->m_bgBattleGroundID)->GetPlayerScoresEnd();++itr)     <<这里肯定出错了。但我没招。水平  
          {  
                  data   <<   (uint64)itr->first;                                                   //8  
                  data   <<   (uint32)itr->second.Rank;                                       //4                                         //Rank  
                  data   <<   (uint32)itr->second.KillingBlows;                       //4  
                  data   <<   (uint32)itr->second.Deaths;                                   //4  
                  data   <<   (uint32)itr->second.HonorableKills;                   //4  
                  data   <<   (uint32)itr->second.DishonorableKills;             //4  
                  data   <<   (uint32)itr->second.BonusHonor;                           //4  
                  data   <<   (uint32)0;  
                  data   <<   (uint32)0;  
                  /*data   <<   itr->second.Rank;  
                  data   <<   itr->second.Unk1;  
                  data   <<   itr->second.Unk2;  
                  data   <<   itr->second.Unk3;  
                  data   <<   itr->second.Unk4;*/  
          }  
          GetPlayer()->GetSession()->SendPacket(&data);  
  }  
  catch(...)  
  {  
  sLog.outDebug("WORLD   ERROR:。WorldSession::HandleBattleGroundPVPlogdataOpcode   has   an   Error   been   throw.");  
  }

9 楼A_B_C_ABC(黄瓜@YouCanDoIt)回复于 2006-05-25 15:11:52 得分 0

    如果发生错误的函数内部代码没有throw异常,那么在函数调用时是try{}catch{}不到任何东西的即,throw   try   catch是配套工作的。还是去检查出错函数代码吧

10 楼DeadWolf(三角小眼睛又邪又媚又笨又呆又奸又诈又色)回复于 2006-05-25 17:55:08 得分 0

    估计是GetBattleGround   或者其他方法返回空指针了

    跟进去看一下就知道了

    或者把这些函数的返回先用指针接下来   在判断指针是否为空

11 楼dreamXren(追梦人)回复于 2006-05-25 18:22:02 得分 0

try   {  
          int   i   =   5   /   0;  
  }   catch   (...)   {  
          //   捕获到异常了  
  }

12 楼code_tin(代码罐头[看来牛魔王快做不成了])回复于 2006-05-25 18:33:38 得分 0

    因为C++的异常是中止型的。   
    所以该出错的地方是肯定还是出错的   

    只是中断以后抛出异常。你的异常处理子程序可以根据异常的类型来做后续处理  
   
    和狗狗一样  
    我本人不喜欢使用异常。  
    一个是增加了执行期负载  
    二是加入了异常感觉把代码切的一块一块的。  
    其实异常和原来的return错误号一样  
    都要自己先判定一些异常情况  
    然后抛出不同的异常并对不同的异常做不同的处理。  
    只是异常可以一层一层的往上抛出。可以把异常处理子程序稍微集中一点  
    还有我大多使用API  
    一般都是返回错误值。如果这个时候只使用异常处理机制的话  
    最后反而可能变成两种错误检测机制都不做了。

13 楼lddLinan(不再五行中)回复于 2006-05-25 19:12:48 得分 0

    异常扑获不到,很可能就是代码本身就没有异常,或者是已经设置了某个函数在异常抛出前调用,而这个函数中止了程序,还有一种是在异常已经抛出后又抛出异常,这时候程序就abort了

14 楼Shatty(西北游侠)回复于 2006-05-25 19:51:27 得分 0

    //By   wrapping   the   body   of   main   in   a   try-catch   block    
    //   we   can   be   assured   that   we'll   catch   all   exceptions    
    //   in   the   exception   hierarchy.   You   can   simply   catch    
    //   exception   as   is   done   below,   or   you   can   catch   each    
    //   of   the   exceptions   in   which   you   have   an   interest.  
  只要是在exception继承层次内的异常,都是可以捕捉到,  
  throw();   Destroys   an   object   of   class   exception.  
  没有在exception层次内的异常也是不会被抛出的.   

15 楼bestia(bestia)回复于 2006-05-25 20:47:17 得分 0

    当然要迷惑了,C++的异常处理简直可以写满满一本书(还真有),如果规则很清晰那这显然是不可能的事

16 楼zhaomu()回复于 2006-05-25 21:02:32 得分 0

    看看

17 楼agaric(蘑菇星星)回复于 2006-05-25 22:20:11 得分 0

    还是喜欢用错误码...

18 楼FreeFice(庄鱼)回复于 2006-05-26 16:45:41 得分 0

    你可以将上述代码改写成其它的形式,毕竟这种代码本身有很多问题。  
    代码书写原则上将每一条指令、函数用独立的行表示,这样差错就容易得多:至少便于隔离错误,找寻问题的关键。

19 楼realorg()回复于 2006-05-26 18:43:48 得分 0

    偶也有一个问题啊~!   
    偶定义了一个时间类   CmyTime   ,  
    但在   main()函数中  
    CmyTime   *pmyTime=new   CmyTime();  
    .....  
    delete   []pmyTime;       //这里出现运行错误,好像是   Assertion   Failed   !!之类的错误信息~!  
   
    请高手指教,这是怎么回事?

20 楼zzstephen(渣渣)回复于 2006-05-26 22:13:53 得分 0

   楼上的,new的是数组采用   delete   [],那个不是数组,所以用delete   pmyTime  
   楼主去看书把,三言两语的的谁也说不清的

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值