記憶體錯誤的類別

2021-09-07 13:39:49 字數 1803 閱讀 7438

首先,不要失去信心。有很多辦法可以對付記憶體問題。我們先列出所有可能存在的實際問題:

這是所有型別。即使遷移到 c++ 物件導向的語言,這些型別也不會有明顯變化;無論資料是簡單型別還是 c 語言的struct或 c++ 的類,c 和 c++ 中記憶體管理和引用的模型在原理上都是相同的。以下內容絕大部分是「純 c」語言,對於擴充套件到 c++ 主要留作練習使用。

在分配資源時會發生記憶體洩漏,但是它從不**。下面是乙個可能出錯的模型(請參見清單 1):

清單 1. 簡單的潛在堆記憶體丟失和緩衝區覆蓋

void f1(char *explanation)

您看到問題了嗎?除非local_log()free()釋放的記憶體具有不尋常的響應能力,否則每次對f1的呼叫都會洩漏 100 位元組。在記憶棒增量分發數兆位元組記憶體時,一次洩漏是微不足道的,但是連續運算元小時後,即使如此小的洩漏也會削弱應用程式。

清單 2. 來自資源錯誤管理的潛在堆記憶體丟失

int getkey(char *filename)

fopen的語義需要補充性的fclose。在沒有fclose()的情況下,c 標準不能指定發生的情況時,很可能是記憶體洩漏。其他資源(如訊號量、網路控制代碼、資料庫連線等)同樣值得考慮。

錯誤分配的管理不是很困難。下面是乙個示例(請參見清單 3):

清單 3. 未初始化的指標

void f2(int datum)

關於此類錯誤的好訊息是,它們一般具有顯著結果。在 aix® 下,對未初始化指標的分配通常會立即導致 segmentation fault 錯誤。它的好處是任何此類錯誤都會被快速地檢測到;與花費數月時間才能確定且難以再現的錯誤相比,檢測此類錯誤的代價要小得多。

在此錯誤型別中存在多個變種。free()釋放的記憶體比malloc()更頻繁(請參見清單 4):

清單 4. 兩個錯誤的記憶體釋放

/* allocate once, free twice. */

void f3()

/* allocate zero times, free once. */

void f4()

這些錯誤通常也不太嚴重。儘管 c 標準在這些情形中沒有定義具體行為,但典型的實現將忽略錯誤,或者快速而明確地對它們進行標記;總之,這些都是安全情形。

懸空指標比較棘手。當程式設計師在記憶體資源釋放後使用資源時會發生懸空指標(請參見清單 5):

清單 5. 懸空指標

void f8() 

傳統的「除錯」難以隔離懸空指標。由於下面兩個明顯原因,它們很難再現:

懸空指標不斷威脅著 c 或 c++ 程式的執行狀態。

陣列邊界違規十分危險,它是記憶體錯誤管理的最後乙個主要類別。回頭看一下清單 1;如果explanation的長度超過 80,則會發生什麼情況?回答:難以預料,但是它可能與良好情形相差甚遠。特別是,c 複製乙個字串,該字串不適於為它分配的 100 個字元。在任何常規實現中,「超過的」字元會覆蓋記憶體中的其他資料。記憶體中資料分配的布局非常複雜並且難以再現,所以任何症狀都不可能追溯到源**級別的具體錯誤。這些錯誤通常會導致數百萬美元的損失。

勤奮和自律可以讓這些錯誤造成的影響降至最低限度。下面我們介紹一下您可以採用的幾個特定步驟;我在各種組織中處理它們的經驗是,至少可以按一定的數量級持續減少記憶體錯誤。

儲存類別,鏈結和記憶體管理

參考資料 根據乙個變數的作用域 可見的範圍 和生命期 它存在多長時間 來劃分儲存類別。根據作用域可分為塊作用域,函式作用域,函式原型作用域,檔案作用域。塊作用域 在 之間都乙個屬於塊作用域。塊裡面定義的變數,作用範圍是從定義處到包含該定義的塊的末尾。函式作用域 這個我也不太清楚,書上講僅用於goto...

C C 中的變數儲存類別以及記憶體分配

1.變數的儲存類別 從變數值存在的角度來分,可以分為靜態儲存方式和動態儲存方式。所謂靜態儲存方式指在程式執行期間由系統分配固定的儲存空間的方式 程式開始執行時分配,在程式完畢時釋放,在程式過程中它們佔據國定的儲存單元,而不是動態分配和釋放 而動態儲存方式在執行期間根據需要進行動態儲存方式 在程式過程...

常見的記憶體錯誤 三

7.結構的成員順序變化引發的錯誤 在初始化乙個結構時,老手可能很少像新手那樣老老實實的,乙個成員乙個成員的為結構初始化,而是採用快捷方式,如 struct s int main int argc,char argv return 0 以上這種方式是非常危險的,原因在於你對結構的記憶體布局作了假設。如...