簡體   English   中英

C++ 異常開銷

[英]C++ exception overhead

為什么嵌入式平台開發人員不斷嘗試從他們的SDKs中刪除使用C++ exceptions

例如, Bada SDK為異常使用建議了以下變通方法,看起來異常難看:

 result
 MyApp::InitTimer()
 {
    result r = E_SUCCESS;

    _pTimer = new Timer;

    r = _pTimer->Construct(*this);
    if (IsFailed(r))
    {
        goto CATCH;
    }

    _pTimer->Start(1000);
    if (IsFailed(r))
    {
        goto CATCH;
    }

    return r;
 CATCH:
     return r;
 }

這種行為的原因是什么?

據我所知, ARM編譯器完全支持C++ exceptions ,這實際上不是問題。 還有什么? ARM平台上的異常使用和展開的開銷真的要花很多時間做這樣的變通方法嗎?

也許還有其他我不知道的東西?

謝謝你。

只是我的2美分...

我專門咨詢嵌入式系統,其中大多數是硬實時和/或安全/生命攸關的。 它們中的大多數運行在 256K 或更少的閃存/ROM 中 - 換句話說,這些不是具有 1GB+ RAM/閃存和 1GHz+ CPU 的“類似 PC”的 VME 總線系統。 它們是深度嵌入、資源有限的系統。

我想說至少 75% 的使用 C++ 的產品在編譯器中禁用異常(即,使用禁用異常的編譯器開關編譯的代碼)。 我總是問為什么。 信不信由你,最常見的答案不是運行時或 memory 開銷/成本。

答案通常是以下幾種:

  • “我們不確定我們知道如何編寫異常安全代碼”。 對他們來說,檢查返回值更熟悉、更簡單、更安全。
  • “假設你只在特殊情況下拋出異常,這些情況下我們無論如何都要重啟 [通過他們自己的嚴重錯誤處理程序例程]”
  • 遺留代碼問題(正如 jalf 所提到的) - 他們正在使用多年前開始的代碼,當時他們的編譯器不支持異常,或者沒有正確或有效地實現它們

此外 - 經常有一些關於開銷的模糊不確定性/恐懼,但幾乎總是它是未量化/未分析的,它只是一種被扔在那里並按面值計算。 我可以向您展示 state 的報告/文章,異常開銷為 3%、10%-15% 或 ~30% - 任您選擇。 人們傾向於引用代表自己觀點的人物。 幾乎總是,文章已經過時,平台/工具集完全不同,等等。正如羅迪所說,你必須在你的平台上衡量自己。

我不一定要為這些立場辯護,我只是給你真實的反饋/解釋,我從許多與 C++ 在嵌入式系統上合作的公司那里聽到,因為你的問題是“為什么這么多嵌入式開發人員避免例外?”

我能想到幾個可能的原因:

  • 舊版本的編譯器不支持異常,因此編寫了很多代碼(並建立了約定),其中不使用異常
  • 異常確實是有代價的,它可能占總執行時間的 10-15%(它們也可以實現為幾乎不花時間,但使用相當多的 memory 代替,這可能不是很理想在嵌入式系統上)
  • 嵌入式程序員往往對代碼大小、性能,尤其是代碼復雜性有點偏執。 他們經常擔心“高級”功能可能無法在他們的編譯器中正常工作(而且他們通常也是正確的)

我認為這主要是 FUD,這些天。

異常確實在創建具有構造函數/析構函數的對象的塊的入口和出口處有少量開銷,但在大多數情況下,這實際上不應該相當於一罐豆子。

先測量,再優化。

但是,拋出異常通常比僅返回 boolean 標志要慢,因此僅針對異常事件拋出異常

在一種情況下,我看到 RTL 正在從符號表構造整個可打印的堆棧跟蹤,只要拋出異常以供潛在的調試使用。 可以想象,這不是一件好事 這是幾年前的事了,當這個問題曝光時,調試庫被匆忙修復。

但是,IMO,您從正確使用異常中獲得的可靠性遠遠超過了輕微的性能損失。 使用它們,但要小心。

編輯:

@jalf 提出了一些很好的觀點,我上面的回答針對的是為什么許多嵌入式開發人員通常仍然貶低例外的相關問題。

但是,如果特定平台 SDK 的開發人員說“不要使用異常”,那么您可能不得不使用 go。 也許他們的庫或編譯器中的異常實現存在特殊問題 - 或者他們擔心回調中拋出的異常會由於他們自己的代碼中缺乏異常安全性而導致問題。

這種對異常的態度與性能或編譯器支持無關,而是與異常增加代碼復雜性的想法有關。

據我所知,這個想法幾乎總是一種誤解,但由於某些不可思議的原因,它似乎有 強大的支持者

與其他答案所支持的“gotos are evil”相反的觀點。 我正在制作這個社區維基,因為我知道這種相反的觀點會被激怒。

任何稱職的實時程序員都知道goto的這種用法。 它是一種廣泛使用且被廣泛接受的錯誤處理機制。 許多硬實時編程環境沒有實現<setjmp.h>。 例外在概念上只是setjmplongjmp的受限版本。 那么,當底層機制被禁止時,為什么要提供異常呢?

如果始終可以保證在本地處理所有拋出的異常,則環境可能允許異常。 問題是,為什么要這樣做? 唯一的理由是 gotos 總是邪惡的。 好吧,他們並不總是邪惡的。

現代 C++ 編譯器可以將異常的運行時使用率降低到低至 3% 的開銷。 盡管如此,如果極端程序員發現它很昂貴,那么他們就會訴諸這種骯臟的伎倆。

請參閱此處 Bjarne Strourstrup 的頁面,了解為什么使用異常?

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM