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