基於C 中常見記憶體錯誤的總結

2021-07-30 07:23:52 字數 2472 閱讀 9379

在系統開發過程中出現的bug相對而言是比較好解決的,花費在這個上面的除錯代價不是很大,但是在系統整合後的bug往往是難以定位的bug(最好方式是打樁,通過打樁可以初步鎖定出錯的位置,如:進入函式前列印日誌,離開時再次列印日誌)。而這些難以定位的bug基本分為2類:記憶體錯誤和並非問題。

1、記憶體洩露

如果在堆疊上分配的記憶體使用完成後沒有釋放就會造成記憶體洩露。少量的記憶體洩露不至於讓程式崩潰,但是大量的記憶體洩露就會導致記憶體耗盡,後續記憶體分配失敗,從而導致程式崩潰。長時間執行軟體,即使只有一兩處洩露,同樣會導致程式崩潰。所以有當出現記憶體洩露請檢查是否釋放了資源。

2、記憶體越界訪問

記憶體越界訪問有兩種:一種是讀越界,即讀了不屬於自己的資料,如果所讀的記憶體位址是無效的,程式就立即崩潰。如果所讀的記憶體位址是有效的,在讀的時候不會出現問題,但是由於讀到的資料是隨機的,他會產生不可預料的後果,另一種是寫越界,又叫緩衝區溢位。所寫的資料是隨機的,他也會產生不可預料的後果。

記憶體越界訪問造成的後果非常嚴重,是引起程式不穩定的主要原因之一,最主要的是它造成的後果是隨機的,表現出來的症狀和時機也是隨機的,讓bug的現象和本質看似沒有什麼聯絡,這給bug定位帶來了極大的困難。所以在時機開發過程中,對於外部傳入的引數要仔細檢查。

3、野指標

釋放掉的記憶體會被記憶體管理器重新分配。此時野指標指向的記憶體已經被賦予新的意義。對野指標指向的記憶體訪問,無論是有意的還是無意的,都會為此付出巨大代價,因為它造成的後果,如果越界訪問一樣是不可預料的。解決野指標最好的方法:釋放記憶體後立即把對應指標置為空值。

4、訪問空指標

在訪問指標指向的記憶體時,確保指標不是空指標。訪問空指標指向的記憶體,通常會導致程式崩潰,或者不可預料的錯誤。

5、引用未初始化的變數

未初始化變數的內容是隨機的,使用這些資料會造成不可預料的後果,除錯這樣的bug也非常困難。最好的解決辦法:在宣告變數的時候就對它進行初始化。

6、不清楚的指標運算

如:int *p=....;

p+n等價於(size_t)p+n*sizeof(*p);

7、結構體成員順序變化引發的錯誤

8、結構體大小變化引發的錯誤

9、分配釋放不配對

10、返回指向臨時變數的指標

棧裡面的變數時臨時的,當前函式執行完成時,先關的臨時變數和引數都被清除了。不能把指向這些臨時變數的指標返回給呼叫這,這樣的指標執行的資料是隨機的,會給程式造成不可預料的後果。

11、試圖修改常量

如:char *p="1234";

*p='1';

12、誤解傳值和傳引用

13、重名符號

關於重名問題可以參考:c++重定**決方法總結

14、棧溢位

15、誤用sizeof

c++通常是按值傳遞引數,而陣列則是例外,在傳遞陣列引數時,陣列退化為指標(及按引用傳遞),此時用sizeof是無法獲取資料的大小。

16、位元組對齊

位元組對齊主要目的是提高記憶體訪問效率,在某些平台上,就不僅僅是效率問題,如果不對齊得到的資料是錯誤的。大多數情況下編譯器會保值全域性變數和臨時變數按照正確的方式對齊。記憶體管理器會保證動態按照正確的方式對齊。要注意的是:在不同的型別的變數之間轉換時要小心。

位元組對齊也會造成結構體大小的變化,在程式內部用sizeof來取的結構的大小就可以了。若資料要在不同的機器間傳遞時,在通訊協議中要規定對齊的方式,避免對齊方式不一致引發的問題。

關於位元組對齊問題請參考:關於c++記憶體中位元組對齊問題的詳細介紹

17、位元組順序

位元組順序歷來是設計跨平台最頭痛的問題。位元組順序是關於資料在物理記憶體中的布局問題,最常見的位元組順序有兩種:大端模式和小端模式

大端模式:高位位元組資料存放在低位址處,低位位元組資料存放在高位址處。

小端模式:低位位元組資料存放在記憶體低位址處,高位元組位元組資料存放在記憶體高位址處

如:long n=0x11223344

模式第1位元組 第2位元組第3位元組  第4位元組

大端模式0x110x220x330x44

小端模式0x440x330x220x11

在普通軟體中,位元組順序問題並不引人注目。而在開發與網路通訊和資料交換有關的軟體時,位元組順序就要多注意了。

18、多執行緒共享變數沒有用valotile修飾

valotile作用:告訴編譯器不要把變數優化到暫存器中。在開發多執行緒的程式是,如果這些執行緒共享一些全域性變數,這些全域性變數最好使用valotile修飾。這樣可以避免因為編譯器優化而引起的錯誤。

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

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

pytorch中常見錯誤總結

錯誤1 在console中輸入import torchvision會報錯 importerror cannot import name pillow version 原因 torchvision和pillow版本不相容,可能pillow版本過高,如pillow 7.0和torchvision 0.3...

C 中常見的程式設計錯誤

1 嘗試修改字串常量 char p i m hungry p 0 s 答案與分析 上面的 能成功通過編譯,但會產生執行時的錯誤即造成記憶體的非法寫操作。i m hungry 實質上是字串常量,而常量往往被編譯器放在唯讀的記憶體區,不可寫。p初始指向這個唯讀的記憶體區,而p 0 i 則企圖去寫這個地方...