2016-02-12 85 views
11

在更高效的C++(第15號)一書中,我發現如果啓用了異常,代碼將變得非常慢,即使它們未被使用。在我看來,例外是有限的使用,我儘量避免它們,但這是另一個話題。如何關閉異常處理?

我不完全理解他的說法:

  1. 是什麼啓用/禁用異常是什麼意思?它是有零還是多於零的try/catch塊之間的區別?它是一個編譯器標誌嗎?如果我使用可能發生異常的DLL,會發生什麼情況?
  2. 假設沒有異常被丟進:
    • 代碼是否變得更慢作爲一個整體或者是隻有當程序進入零件/退出try/catch塊變慢?據作者說,兩者都是事實。
  3. 我該如何編譯沒有例外?我可以做到這一點,即使我有try/catch塊嗎?如果我使用的DLL可能會引發異常,我可以這樣做嗎?
+1

這本書很舊,編譯器從此變得更聰明。今天體面的一個可以做到零開銷,使用指令地址的基於表的查找來查找堆棧解開時需要運行的代碼。但是,如果您想要了解它,然後查看編譯器選項,大多數都可以選擇禁用該功能。 –

+0

「在我看來,例外是有限的使用,我儘量避免它們,但這是另一個話題。」我的猜測是你的代碼不會調用任何可能的系統調用。你正在編程CPU加熱器嗎? – 2016-03-08 18:22:17

+0

@ user4590120:異常並不是處理故障的唯一方法。我使用返回代碼來檢查成功或失敗。 – Fabian

回答

6

啓用/禁用異常是什麼意思?

將標誌傳遞給編譯器,該標誌禁用與異常有關的標準一致性,並且不會產生任何異常支持。

如果我使用可能發生異常的DLL,會發生什麼情況?

如果某個庫在內部處理異常,則爲空。如果它讓它逃到調用者(由於ABI問題,我從來沒有見過任何這樣做的庫,但無論如何),你的程序崩潰(最好的情況),因爲它無法處理它。如果您的代碼包含的DLL包裝器將錯誤代碼轉換爲異常(常見事件),那麼它與您在代碼中使用異常的情況相同。

代碼整體變慢還是隻是程序進入/退出try/catch塊變慢的部分?據作者說,兩者都是事實。

請注意,你所引用的書是舊的。編譯器正在發展。現代編譯器使用零成本異常,如果不拋出異常,則不會導致性能成本。異常處理確實使可執行文件變得更大,因爲它應該生成處理異常所需的所有數據和代碼,但不應使其在非例外路徑上變慢。

我如何編譯沒有例外?我可以做到這一點,即使我有try/catch塊嗎?

你以編譯器特定的方式做到這一點。請查閱你的編譯器文檔通常這樣做會使編譯器拒絕包含任何異常相關設施的代碼,例如指出try爲無法識別的標識符。

+1

「異常處理確實使可執行文件更大」 - 比什麼更大?具有錯誤返回值的等效程序也需要代碼和數據來處理這些。例外的一大優點是,錯誤處理代碼和數據最初可以留在磁盤上,這樣您的程序就可以更快地啓動。 – MSalters

+0

「它不應該讓它在非常規路徑上變慢」 - 實際上,現代異常處理使得非錯誤路徑_faster_。這是因爲編譯器可以識別並優化該路徑。由於錯誤返回值,編譯器不知道是否優化「== 0」或「!= 0」返回值,因爲不同的函數使用不同的返回值約定。 – MSalters

+1

@MSalters比完全相同的代碼編譯時沒有異常支持(這意味着原始代碼必須沒有異常處理)。這樣就避免了標準庫的異常處理(例如,'new'通常會變成nothrow'new',例如用空指針訪問崩潰來代替'bad_alloc'異常) –