上一個帖子“語法”由于篇幅有限,沒來得及聊異常,現(xiàn)在把和異常相關的部分單獨拿出來說一下。
★小心new分配內存失敗
早期的老式編譯器生成的代碼,如果new失敗會返回空指針。我當年用的Borland C++ 3.1似乎就是這樣的,現(xiàn)在這種編譯器應該不多見了。如果你目前用的編譯器還有這種行為,那你就慘了。你可以考慮重載new操作符來拋出bad_alloc異常,便于進行異常處理。
稍微新式一點的編譯器,就不是僅僅返回空指針了。當new操作符發(fā)現(xiàn)內存告急,按照標準的規(guī)定(參見03標準18.4.2章節(jié)),它應該去調用new_handler函數(shù)(原型為typedef void (*new_handler)();)。標準建議new_handler函數(shù)干如下三件事:1、設法去多搞點內存來;2、拋出bad_alloc異常;3、調用abort()或者exit()退出進程。由于new_handler函數(shù)是可以被重新設置的(通過調用set_new_handler),所以上述的行為它都可能有。
綜上所述,new分配內存失敗,有可能三種可能:1、返回空指針;2、拋出異常;3、進程立即終止。如果你希望你的代碼具有較好的移植性,你就得把這三種情況都考慮到。
★慎用異常規(guī)格
異常規(guī)格在我看來不是一個好東西,不信可以去看看《C++ Coding Standards - 101 Rules, Guidelines & Best Practices》的第75條。(具體有哪些壞處以后專門開一個C++異常和錯誤處理的帖子來聊)言歸正傳,按照標準(參見03標準18.6.2章節(jié)),如果一個函數(shù)拋到外面的異常沒有包含在該函數(shù)的異常規(guī)范中,那么應該調用unexcepted()。但是并非所有編譯器生成的代碼都遵守標準(比如某些版本的VC編譯器)。如果你的需要支持的編譯器在異常規(guī)范上的行為不一致,那就得考慮去掉異常規(guī)范聲明。
★不要跨模塊拋出異常
此處說的模塊是指動態(tài)庫。如果你的程序包含有多個動態(tài)庫,不要把異常拋到模塊的導出函數(shù)之外。畢竟現(xiàn)在C++還沒有ABI標準(估計將來也未必會有),跨模塊拋出異常會有很多不可預料的行為。
★不要使用結構化異常處理(SEH)
如果你從來沒有聽說過SEH,那就當我沒說,跳過這段。如果你以前習慣于用SEH,在你打算寫跨平臺代碼之前,要改掉這個習慣。包含有SEH的代碼只能在Windows平臺上編譯通過,肯定無法跨平臺的。
★關于catch(...)
照理說,catch(...)語句只能夠捕獲C++的異常類型,對于訪問違例、除零錯等非C++異常是無能為力的。但是某些情況下(比如某些VC編譯器),諸如訪問違例、除零錯也可以被catch(...)捕獲。所以,你如果希望代碼移植性好,就不能在程序邏輯中依賴上述catch(...)的行為。
下一個帖子,準備聊一下和“硬件有關的跨平臺問題”。
★小心new分配內存失敗
早期的老式編譯器生成的代碼,如果new失敗會返回空指針。我當年用的Borland C++ 3.1似乎就是這樣的,現(xiàn)在這種編譯器應該不多見了。如果你目前用的編譯器還有這種行為,那你就慘了。你可以考慮重載new操作符來拋出bad_alloc異常,便于進行異常處理。
稍微新式一點的編譯器,就不是僅僅返回空指針了。當new操作符發(fā)現(xiàn)內存告急,按照標準的規(guī)定(參見03標準18.4.2章節(jié)),它應該去調用new_handler函數(shù)(原型為typedef void (*new_handler)();)。標準建議new_handler函數(shù)干如下三件事:1、設法去多搞點內存來;2、拋出bad_alloc異常;3、調用abort()或者exit()退出進程。由于new_handler函數(shù)是可以被重新設置的(通過調用set_new_handler),所以上述的行為它都可能有。
綜上所述,new分配內存失敗,有可能三種可能:1、返回空指針;2、拋出異常;3、進程立即終止。如果你希望你的代碼具有較好的移植性,你就得把這三種情況都考慮到。
★慎用異常規(guī)格
異常規(guī)格在我看來不是一個好東西,不信可以去看看《C++ Coding Standards - 101 Rules, Guidelines & Best Practices》的第75條。(具體有哪些壞處以后專門開一個C++異常和錯誤處理的帖子來聊)言歸正傳,按照標準(參見03標準18.6.2章節(jié)),如果一個函數(shù)拋到外面的異常沒有包含在該函數(shù)的異常規(guī)范中,那么應該調用unexcepted()。但是并非所有編譯器生成的代碼都遵守標準(比如某些版本的VC編譯器)。如果你的需要支持的編譯器在異常規(guī)范上的行為不一致,那就得考慮去掉異常規(guī)范聲明。
★不要跨模塊拋出異常
此處說的模塊是指動態(tài)庫。如果你的程序包含有多個動態(tài)庫,不要把異常拋到模塊的導出函數(shù)之外。畢竟現(xiàn)在C++還沒有ABI標準(估計將來也未必會有),跨模塊拋出異常會有很多不可預料的行為。
★不要使用結構化異常處理(SEH)
如果你從來沒有聽說過SEH,那就當我沒說,跳過這段。如果你以前習慣于用SEH,在你打算寫跨平臺代碼之前,要改掉這個習慣。包含有SEH的代碼只能在Windows平臺上編譯通過,肯定無法跨平臺的。
★關于catch(...)
照理說,catch(...)語句只能夠捕獲C++的異常類型,對于訪問違例、除零錯等非C++異常是無能為力的。但是某些情況下(比如某些VC編譯器),諸如訪問違例、除零錯也可以被catch(...)捕獲。所以,你如果希望代碼移植性好,就不能在程序邏輯中依賴上述catch(...)的行為。
下一個帖子,準備聊一下和“硬件有關的跨平臺問題”。