常見的記憶體錯誤及其對策

2022-08-26 19:18:12 字數 2718 閱讀 5272

作業系統複習

特點

編譯器不能自動發現這類錯誤,通常是在程式執行時才能捕捉到

時隱時現,無明顯症狀

分類

1 記憶體分配未成功,卻使用了它

起因 沒有意識到記憶體分配會不成功 程式設計新手容易犯

解決對策 在使用記憶體之前,檢查指標是否為空指標(null)

char *p = (char *) malloc(100

);

if (p ==null)

view code

2 記憶體分配成功,但是尚未初始化就引用它

起因 沒有初始化的觀念 誤以為記憶體的預設值全為0

實際情況 

記憶體的預設初值究竟是什麼並沒有統一的標準。但是對於全域性變數和靜態變數如果沒有手工初始化,編譯器會將其初始化為零,而對棧記憶體和堆記憶體則不作任何處理。

另外,vc在debug和release狀態下在初始化變數時所做的操作是不同的。debug是將每個位元組位都賦值成0xcc,以有利於除錯。而release的賦值是直接從記憶體中分配的,內容近似於隨機。所以如果在沒有初始化變數的情況下去使用它的值,就會導致問題發生。

解決對策 即使是賦0值也不可省略,不要嫌麻煩

3 記憶體分配成功,並且已經初始化,但操作越過了記憶體的邊界

記憶體分配成功,並且已經初始化,但操作越過了記憶體的邊界 例如:使用陣列時經常發生下標「多1」或者「少1」的操作

解決對策: 在for語句中,注意迴圈次數不要搞錯

訪問越界會出現什麼結果?

首先,它並不會造成編譯錯誤! 就是說,c/c++的編譯器並不判斷和指出**「訪問越界」了。此外,陣列訪問越界在執行時,它的表現是不定的,有時似乎什麼事也沒有,程式一直執行(當然,某些錯誤結果已造成);有時,則是程式一下子崩潰。

4 忘記了釋放記憶體,造成記憶體洩漏

忘記釋放記憶體,造成記憶體洩漏(memory leak) 「記憶體洩露」一詞類似「原料洩露」 洩露出去的原料不能被利用,導致生產過程中原料不足。好比借東西不還 如果申請來的記憶體不用,別的程式也不能用,就好像這塊記憶體洩露出去一樣,造成浪費。

以下這段小程式演示了堆記憶體發生洩漏的情形:

void myfunction(int

nsize)…//

using the string pointed by p;

delete

p;}

view code

當函式getstringfrom()返回零的時候,指標p指向的記憶體就不會被釋放。這是一種常見的發生記憶體洩漏的情形。程式在入口處分配記憶體,在出口處釋放記憶體,但是c函式可以在任何地方退出,所以一旦對分支處理不完整或者錯誤處理不當的話,就會發生記憶體洩漏。雖然函式體內的區域性變數在函式結束時自動消亡,但是區域性的指標變數所指向的記憶體並不會被自動釋放。

動態記憶體的申請與釋放必須配對,如果程式在入口處動態申請了記憶體,那麼在程式的每個出口處都必須釋放該記憶體空間。

解決對策

在需要的時候才malloc,並儘量減少malloc的次數 malloc的執行效率就不高,過多的malloc使程式效能下降 能用自動變數解決的問題,就不要用malloc來解決 malloc一般在大塊記憶體分配和動態記憶體分配時使用

重複使用malloc申請到的記憶體

盡量讓malloc和與之配套的free在乙個函式或模組內 盡量把malloc集中在函式的入口處,free集中在函式的出口處

5 釋放了記憶體,卻繼續使用它

free

(ptr);

if (ptr != null) //

不起作用

view code

有三種情況:

(a) 程式中的物件呼叫關係過於複雜,實在難以搞清楚某個物件究竟是否已經釋放了記憶體,此時應該重新設計資料結構,從根本上解決物件管理的混亂局面。

(b) 函式的return語句寫錯了,注意不要返回指向「棧記憶體」的「指標」或者「引用」,因為該內存在函式體結束時被自動銷毀。

(c) 使用free釋放了記憶體後,沒有將指標設定為null。導致產生「野指標」,即不是null指標,而是指向「垃圾」記憶體的指標。「野指標」是很危險的,因為使用if語句進行判斷對它不起作用。

char *p = (char *) malloc(100

);strcpy(p, 「hello」);

free(p); //

p 所指的記憶體被釋放,但是p所指的位址仍然不變

…if(p != null) //

沒有起到防錯作用

view code

解決對策

盡量把malloc集中在函式的入口處,free集中在函式的出口處

如果free不能放在函式出口處,則指標free後立即設定為null

不要把區域性變數的位址作為返回值返回,因為該內存在函式體結束時被自動銷毀

指標要麼初始化為null,要麼是其指向合法的記憶體

非法記憶體操作

起因

記憶體分配未成功,卻使用了它

記憶體分配成功,但是尚未初始化就引用它

記憶體分配成功,並且已經初始化,但操作越過了記憶體的邊界

釋放了記憶體,卻繼續使用它

基本特徵

**訪問了不該訪問的記憶體位址

後果

幾乎全是由指標混亂導致的

少數情況下,如在硬體驅動程式中的記憶體問題會造成作業系統的死亡

常見記憶體錯誤及其對策

常見記憶體錯誤及其對策 發生記憶體錯誤是件非常麻煩的事情。編譯器不能自動發現這些錯誤,通常是在程式執行時才能捕捉到。而這些錯誤大多沒有明顯的症狀,時隱時現,增加了改錯的難度。有時使用者怒氣沖沖地把你找來,程式卻沒有發生任何問題,你一走,錯誤又發作了。常見的記憶體錯誤及其對策如下 一 記憶體分配未成功...

常見的記憶體錯誤及其對策

1.常見的記憶體錯誤及其對策 記憶體未分配成功卻使用了它 在使用記憶體之前檢查指標是否為null。如果指標p是函式的引數,那麼在函式的入口處用assert p null 進行檢查 如果使用malloc或者new來申請記憶體,應該用if p null 或if p null 進防錯處理。無論用何種方式建...

常見的記憶體錯誤及其對策

1,常見錯誤及其處理策略 1 記憶體分配未成功,卻使用了它。程式設計新手常犯這種錯誤,因為他們沒有意識到記憶體分配會不成功。常用解決辦法是,在使用記憶體之前檢查指標是否為null。如果指標p是函式的引數,那麼在函式的入口處用assert p null 進行 檢查。如果是用malloc或new來申請記...