C 的可移植性和跨平台開發 3 異常處理

2021-08-23 12:57:23 字數 1391 閱讀 3033

上乙個帖子「語法」由於篇幅有限,沒來得及聊異常,現在把和異常相關的部分單獨拿出來說一下。

小心new分配記憶體失敗

早期的老式編譯器生成的**,如果new失敗會返回空指標。我當年用的borland c++ 3.1似乎就是這樣的,現在這種編譯器應該不多見了。如果你目前用的編譯器還有這種行為,那你就慘了。你可以考慮過載new操作符來丟擲 bad_alloc異常,便於進行異常處理。

稍微新式一點的編譯器,就不是僅僅返回空指標了。當new操作符發現記憶體告急,按照標準的規定 (參見c++ 03標準18.4.2章節),它應該去呼叫new_handler函式(原型為typedef void (*new_handler)();)。標準建議new_handler函式幹如下三件事:1、設法去多搞點記憶體來;2、丟擲bad_alloc異常;3、呼叫abort()或者exit()退出程序。由於new_handler函式是可以被重新設定的(通過呼叫set_new_handler), 所以上述的行為它都可能有。

綜上所述,new分配記憶體失敗,有可能三種可能:1、返回空指標;2、丟擲異常;3、程序立即終止。如果你希望你的**具有較好的移植性,你就得把這三種情況都考慮到。

慎用異常規格

異常規格在我看來不是乙個好東西,不信可以去看看《c++ coding standards - 101 rules, guidelines & best practices》的第75條。(具體有哪些壞處以後專門開乙個c++異常和錯誤處理的帖子來聊)言歸正傳,按照標準(參見03標準18.6.2章 節),如果乙個函式拋到外面的異常沒有包含在該函式的異常規範中,那麼應該呼叫unexcepted()。但是並非所有編譯器生成的**都遵守標準(比如 某些版本的vc編譯器)。如果你的需要支援的編譯器在異常規範上的行為不一致,那就得考慮去掉異常規範宣告。

不要跨模組丟擲異常

此處說的模組是指動態庫。如果你的程式包含有多個動態庫,不要把異常拋到模組的匯出函式之外。畢竟現在c++還沒有abi標準(估計將來也未必會有),跨模組丟擲異常會有很多不可預料的行為。

不要使用結構化異常處理(seh)

如果你從來沒有聽說過seh,那就當我沒說,跳過這段。如果你以前習慣於用seh,在你打算寫跨平台**之前,要改掉這個習慣。包含有seh的**只能在windows平台上編譯通過,肯定無法跨平台的。

關於catch(...)

照理說,catch(...)語句只能夠捕獲c++的異常型別,對於訪問違例、除零錯等非c++異常是無能為力的。但是某些情況下(比如某些vc編譯 器),諸如訪問違例、除零錯也可以被catch(...)捕獲。所以,你如果希望**移植性好,就不能在程式邏輯中依賴上述catch(...)的行為。

下乙個帖子,準備聊一下和「硬體有關的跨平台問題」。

C 的可移植性和跨平台開發 3 異常處理

小心new分配記憶體失敗 早期的老式編譯器生成的 如果new失敗會返回空指標。我當年用的borland c 3.1似乎就是這樣的,現在這種編譯器應該不多見了。如果你目前用的編譯器還有這種行為,那你就慘了。你可以考慮過載new操作符來丟擲bad alloc異常,便於進行異常處理。稍微新式一點的編譯器,...

C 的可移植性和跨平台開發 0 概述

今天聊聊c 的可移植性問題。如果你平時使用c 進行開發,並且你對c 的可移植性問題不是非常清楚,那麼我建議你看看這個系列。即使你目前沒有跨平台開發的需要,了解可移植性方面的知識對你還是很有幫助的。c 的可移植性這個話題很大,包括了編譯器 作業系統 硬體體系等很多方面,每乙個方面都有很多內容。鑑於本人...

C 的可移植性和跨平台開發 2 語法

目前還有相當一部分開發人員在使用老式編譯器幹活,這些老式編譯器可能對c 98支援不夠。因此,當你的 移植到這些老式的編譯器上時,可能會碰到一些稀奇古怪的問題 包括編譯出錯和執行時錯誤 下面這些注意事項有助於你繞過這些問題。強調一下,後面提到的好幾個條款都是通過迴避c 的新語法來保證移植性。如果你用的...