C 安全編碼 函式

2021-09-12 10:29:04 字數 2045 閱讀 4302

由於c語言風格的陣列,預設沒有結束符,當讀取陣列時需要自己根據陣列長度進行判斷。(這個也是c/c++)比其他語言執行效率高的一點原因。

對於設計成api的函式,必須對引數進行合法性判斷,嚴禁在api實現過程中產生crash。

assert,第一會產生crash,release版本又無效;所以assert就顯得沒有意義。

如果引數是指標型引數,且內容不會被修改,請定義為const型別。

不可重入函式在多執行緒環境下其執行結果不能達到預期效果,需謹慎使用。常見的不可重入函式包括:

rand, srand

getenv, getenv_s

strtok

strerror

asctime, ctime, localtime, gmtime

setlocale

atomic_init

tmpnam

mbrtoc16, c16rtomb, mbrtoc32, c32rtomb

gethostbyaddr

gethostbyname

inet_ntoa

可重入概念(簡而言之是可以重複進入,非同步訊號安全):若乙個程式或子程式可以「在任意時刻被中斷然後作業系統排程執行另外一段**,這段**又呼叫了該子程式不會出錯」,則稱其為可重入(reentrant或re-entrant)的。即當該子程式正在執行時,執行執行緒可以再次進入並執行它,仍然獲得符合設計時預期的結果。與多執行緒併發執行的執行緒安全不同,可重入強調對單個執行緒執行時重新進入同乙個子程式仍然是安全的。

乙個函式是可重入的,則該函式應當滿足下述條件:

可重入維基百科

可重入與執行緒安全:

可重入與執行緒安全兩個概念都關係到函式處理資源的方式。但是,他們有重大區別

可重入概念會影響函式的外部介面,而執行緒安全只關心函式的實現。

大多數情況下,要將不可重入函式改為可重入的,需要修改函式介面,使得所有的資料都通過函式的呼叫者提供。

要將非執行緒安全的函式改為執行緒安全的,則只需要修改函式的實現部分。一般通過加入同步機制以保護共享的資源,使之不會被幾個執行緒同時訪問。

作業系統背景與cpu排程策略:

可重入是在單執行緒作業系統背景下,重入的函式或者子程式,按照後進先出的線性序依次執行完畢。

多執行緒執行的函式或子程式,各個執行緒的執行時機是由作業系統排程,不可預期的,但是該函式的每個執行執行緒都會不時的獲得cpu的時間片,不斷向前推進執行進度。

可重入函式未必是執行緒安全的;執行緒安全函式未必是可重入的。

例如,乙個函式開啟某個檔案並讀入資料。這個函式是可重入的,因為它的多個例項同時執行不會造成衝突;但它不是執行緒安全的,因為在它讀入檔案時可能有別的執行緒正在修改該檔案,為了執行緒安全必須對檔案加「同步鎖」。(存疑!!!)

另乙個例子,函式在它的函式體內部訪問共享資源使用了加鎖、解鎖操作,所以它是執行緒安全的,但是卻不可重入。因為若該函式乙個例項執行到已經執行加鎖但未執行解鎖時被停下來,系統又啟動該函式的另外乙個例項,則新的例項在加鎖處將轉入等待。如果該函式是乙個中斷處理服務,在中斷處理時又發生新的中斷將導致資源死鎖。fprintf函式就是執行緒安全但不可重入。

下述例子,是執行緒安全的,但不是可重入的。

int function()

多執行緒執行時,獲得了互斥鎖的執行緒總能獲得cpu時間片,向前推進執行進度,最終解開互斥鎖,使得別的執行緒也能獲得互斥鎖進入臨界區。但是,如果在單執行緒背景下第一次執行該函式時已經獲得互斥鎖進入臨界區,這時該函式被重入執行,這將在重新申請互斥鎖時被餓死(starvation),因為獲得了互斥鎖的該函式的第一次執行將永遠沒有機會再獲得cpu時間片。

如果字串或者指標作為函式引數,為了防止空指標引用錯誤,在引用前必須確保該引數不為null,如果上層調

用者已經保證了該引數不可能為null,在呼叫本函式時,在函式開始處可以加assert進行校驗。 例如下面的代

碼,因為byte *p有可能為null,因此在使用前需要進行判斷。

assert用於檢測**設計上的錯誤,如果assert被觸發,說明**的設計不符合編碼人員的預期。 在函式的開始

處,對引數進行必要的assert操作,可以在測試階段有效地檢驗編碼人員對**設計上的預期。

《C和C 安全編碼》目錄

原文 看 c和c 安全編碼 這本書時,覺得寫得非常的不錯,總結了程式設計時容易出現錯誤的地方,所以自己總結一遍。本篇文章是 c和c 安全編碼 小節目錄,本次將會乙個小節一篇文章的方式進行逐步總結,每次更新一小節。書中的原始碼會親自編碼並將原始碼放在小節講解中。文章主要公布在個人 和csdn部落格。第...

C安全編碼 預處理

建議 規則 巨集是危險的,用法與真正的函式相似,但是具有不同的語義。c99在c中增加了內聯函式,當內聯函式和巨集可以互換使用時,應該優先選擇內聯函式,內聯替換並不是文字替換,也沒有建立函式,決定乙個函式是否為內聯函式是乙個底層的優化細節,編譯器應該不依賴程式換做出這個決定,是否使用內聯函式取決於目標...

C安全編碼 陣列

建議 規則 void clear int array void dowork void clear 使用sizeof array sizeof array 0 這種用法確定這個陣列的元素數量,但由於array是乙個形參,因此它是指標型別,sizeof array sizeof int 4 32位os...