編寫安全程式碼:不要在標頭檔案中定義變數
部落格:blog.focus-linux.net linuxfocus.blog.chinaunix.net
==========================================================================================================================================================
今天這個主題很簡單。但是這麼一個初級問題,居然真正發生在我的周圍。
前幾天幫助同事檢查一個問題。他這樣描述該現象:他定義了一個全域性變數,然後呼叫一個函式F修改了該全域性變數,但是退出函式時該全域性變數的值又被改了。我到他的除錯環境中,先檢視了一下現象。問題重現了。—— 我一直認為,所有能夠重現的問題都不是問題。只要能夠重現,就一定可以修正。
對於這一問題,我的第一反應是競爭引起的。於是我首先使用GDB的set scheduler-locking on,保證其它執行緒處於停止狀態,避免競爭。又試了一次,問題還是存在。在函式退出的時候,列印了一下當時的值。然後退出,再次列印,發現其值變為了初始值。感覺確實有點奇怪。於是看了看他的程式碼,一看該全域性變數定義在標頭檔案中static int g_variable = 0。看到這裡,儘管我不知道其它程式碼是怎麼寫的。我就想到了問題的原因。這裡的全域性變數g_variable肯定有兩份。函式F和呼叫者一定在不同的檔案中,它們都include了這個標頭檔案。結果在函式F中修改了一個g_variable,而呼叫者中使用和檢視的是另一個g_variable。解決方法是,去一個c檔案中定義這個全域性變數,然後到標頭檔案中宣告。
雖然我很快的解決了這個問題。但是我卻想,這個問題真的是一個很初級的問題。而我這位同事已經是一名senior的開發人員了。為什麼還會犯這種錯誤呢?這裡我對事不對人。主要的原因還是對於程式設計的基礎沒有理解。標頭檔案中不要定義全域性變數,看似是一條死的規則。其實只要真正領會什麼是標頭檔案,標頭檔案是如何include到.c原始檔中的。這條規則根本不需要記憶,而是一種理解。這樣會自然的就會寫出正確的程式碼,而不會犯這樣的錯誤。
說到這裡,簡單說一下標頭檔案的知識。標頭檔案的作用,主要是用於宣告變數,函式等等,然後可以被多個原始檔引用。其實我認為其根本目的,一是為了程式碼的整齊,更重要是為了消除重複的程式碼。因為多個原始檔都要相同的宣告,這時就可以用一行include 標頭檔案來解決。而include,在預編譯階段,實際上是將標頭檔案中所有的程式碼都插入到include的位置。真正理解了這個過程,肯定不會犯本文中的這個錯誤。
相關文章
- extern 用法,全域性變數與標頭檔案(重複定義)變數
- 易優CMS模板標籤assign定義變數模板檔案中定義變數,可在其他標籤裡使用該變數變數
- C語言中的標頭檔案中的巨集定義C語言
- 8.10 標頭檔案剖析:變數宣告變數
- 巨集_變數_函式_指標_標頭檔案變數函式指標
- 為什麼不在標頭檔案做定義
- maven中properties標籤定義變數Maven變數
- mac CLion cmake 呼叫自己定義的標頭檔案Mac
- 程式碼重構:檔案相關變數命名約定變數
- vscode 自定義c++標頭檔案,編譯過程中遇到的問題VSCodeC++編譯
- pycharm設定python標頭檔案模版PyCharmPython
- 8.13 標頭檔案剖析:標頭檔案路徑(下)
- 在 C 中引用匯編語言定義的 .globl 變數變數
- 02@在類的標頭檔案中儘量少引入其他標頭檔案
- C語言通過.h標頭檔案引入自己寫的源程式C語言
- mybatis實現變數定義,實現sql業務程式碼MyBatis變數SQL
- locate標頭檔案和庫檔案
- c++中模板類的成員函式的宣告與定義應該放在標頭檔案裡C++函式
- 建立程式編寫demo.py檔案
- 在程式中定義多個同值不同名的變數變數
- 標頭檔案講解
- 祖傳標頭檔案
- 01 shell程式設計之變數定義程式設計變數
- typora編寫md檔案文字設定顏色
- MySQL中變數的定義和變數的賦值使用MySql變數賦值
- 程式碼安全之上傳檔案
- 程式碼安全之檔案包含
- Shell程式設計-shell變數2-位置變數和預定義變數程式設計變數
- .yaml引數檔案的編寫和使用YAML
- JavaScript中是如何定義私有變數的JavaScript變數
- vs2015 設定了包含路徑還是提示說打不開標頭檔案
- 使用 F# 編寫檔案處理程式
- 01.變數定義變數
- shell程式設計02——變數定義與使用程式設計變數
- java安全編碼指南之:檔案IO操作Java
- C++ 的靜態成員變數為什麼一定要在類外定義C++變數
- 標頭檔案的作用分析
- 什麼是 標頭檔案
- 網路標準之:IANA定義的傳輸編碼