C 程式當中異常安全的思考

2022-11-30 13:45:06 字數 1767 閱讀 4636

資源管理(managing resources)始終是c++語言乙個十分重要的話題,也是程式設計師在使用c++編寫**時需要十分注意的地方,稍有不慎就可能導致資源洩漏(resource leak),在筆者以往的程式設計實踐中就經常遇到此類問題。而「resource acquisition in initialization」是一種處理此類問題的較好方法,這是stroustrup博士在演講中所提到的。關於這一點,在d&e [1] 以及相關** [2] 中也有所提及。

該方法使用乙個類來代表對資源的管理邏輯,將指向資源的控制代碼(指標或引用)通過建構函式傳遞給該類,在該類的例項被銷毀時由析構函式負責釋放資源。可以在建立該類的例項之前申請資源,也可以在構造時由該類負責申請資源。這種方式的基本思路是,不論異常是否發生,由於c++的語言機制保證了,一定會呼叫位於當前範圍(scope)的物件的析構函式,所以只要在析構函式中加入資源**的**,那麼這些**總是會被執行的。

這種方法的好處在於,由於將資源**的邏輯通過單獨的類從原有**中剝離出來,使程式設計師總是不會遺漏,思路也變得清晰。

以筆者之見,「resource acquisition in initialization」技法,在處理有關異常的問題時,其適用範圍還可以擴充套件。不單涉及資源管理,只要當scope裡存在類似於fopen/fclose、new/delete這樣的對稱操作時,就可以酌情考慮採用這種方法。避免資源洩漏固然是頭等大事,應該列於基本保證(basic guarantee)之內。

但某些對稱操作,如果會影響程式的正常執行甚至是產生致命錯誤(fatal error)的話,那麼也是不可輕視的。而對於乙個軟體而言,杜絕fatal error應該也算是乙個basic guarantee了。

以下是筆者在實踐中遇到的乙個例子。有意思的是,這個例子是本人在所負責的軟體模組中首次決定使用異常處理機制所遇到的,可謂出師不利:)經過簡化後的**基本如下:

函式f的作用是對傳入其scope的pobj所指物件進行某些操作。當最初引入異常處理機制時,**改變如下:

此處再度throw是為了使f的呼叫者能有機會做一些處理,這是在設計時所需要的。類似這樣的做法在一般的異常處理程式中是很常見的,但是筆者的疏忽卻另自己吃了大虧。雖然,從經過簡化的**中很容易看出破綻來,但是由於當時經驗不足,加之程式邏輯複雜,直到測試時通過最終的使用者介面才發現了問題。

經過幾個小時的艱苦除錯,最後發現問題出在f函式。事實上,函式f的行為隱含了乙個斷言(assert),即:f保證不對pobj所指物件的不可編輯狀態做出更改,在呼叫f前物件是不可編輯的,呼叫後仍然如此。

而在上述程式中,當異常發生時,由於沒有執行pobj->editable(false)這一語句,所以導致程式最終出錯,而且這一錯誤隱蔽在無數**中,異常情況又並非每次都發生,使筆者在除錯時定位錯誤花費了不少精力。

在找到了錯誤根源之後,筆者採用了如下的補救措施,這一做法被stroustrup博士稱為***** use:

在寫下這段**的時候,直覺告訴自己,這裡存在bed smell,但是由於時間緊迫,所以當時暫且容忍了這種quick and dirty的做法。正如stroustrup博士在d&e中所指出的,

這種做法的缺點是囉嗦,冗長乏味,而且可能代價昂貴。仔細分析一下,就可以看出這裡存在的潛在危險:兩處pobj->editable(false)事實上是重複**,我們需要始終保持兩處**的一致性,如果一段時間後,需要在pobj中增加一種類似editable的屬性,這種一致性的保持,就需要延續,很難保證不會再次疏忽.

於是,遵照大師的教誨,筆者增加了乙個輔助類,**如下:

c_handle的建構函式和析構函式中,對_pobj所指物件的操作是成對出現的,所以在以後擴充套件時也不容易出錯。此時f函式的**也變得簡潔了許多:

C 程式的結構

實驗五c 程式的結構 2學時 一 實驗目的 1觀察程式執行中變數的作用域 生存期和,lj 性。2 學習類的靜態成員的使用。3 學習多檔案結構在c 程式中的使用。二 實驗任務 1 執行下面的程式,觀察變數x y的值。include void fnl int x 1,y 2 int x 1,y 2 in...

C程式的執行環境和執行C程式的方法

實驗1 c程式的執行環境和執行c程式的方法實驗內容 1 輸入並執行乙個簡單 正確的程式。要求程式名為 include int main 仔細觀察螢幕上的已輸入程式,檢查有無錯誤。然後編譯,連線,執行。2 輸入並編輯乙個有錯誤的c程式。要求程式名為 輸入教材第一章例1.2,故意漏打或打錯幾個字元。進行...

實驗一C程式的執行環境和執行C程式的方法

1.實驗目的 1 了解所用的計算機系統的基本操作方法,學會獨立使用該系統。2 了解在該系統上如何編輯 編譯 連線和執行乙個c程式。3 通過執行簡單的c程式,初步了解c程式的特點。2.實驗內容和步驟 1 檢查所用的計算機系統是否已安裝了c編譯系統並確定它所在的子目錄。2 進人c的工作環境 3 熟悉整合...