對C++異常處理的討論

來源:互聯網
上載者:User

源自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   或者其他方法返回null 指標了

    跟進去看一下就知道了

    或者把這些函數的返回先用指標接下來   在判斷指標是否為空白

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  
   樓主去看書把,三言兩語的的誰也說不清的

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.