C 記憶體常見錯誤

2021-08-29 18:36:38 字數 1845 閱讀 7174

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

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

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

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

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

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

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

如:int *p=....;

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

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

如:char *p="1234";

*p='1';

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

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

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

具體詳細細節見

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

如:long n=0x11223344

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

大端模式0x110x220x330x44 

小端模式0x440x330x220x11

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

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

C 常見記憶體錯誤彙總

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

C 常見記憶體錯誤彙總

c 中記憶體錯誤通常屬於執行時錯誤,只有在程式執行時才能發現,編譯器無法自動檢測到記憶體錯誤。多數情況下是程式邏輯或者引數存在某些錯誤。下面總結一下c 常見的記憶體錯誤 1.記憶體洩露 記憶體洩露是指應用程式未釋放動態申請的且不再使用的記憶體,原因可能是程式設計師疏忽或者錯誤造成程式異常。在c c ...

常見的C記憶體管理錯誤

1 初始化錯誤。例如 malloc 返回的空間沒有進行初始化 2 未檢查返回值 3 對空指標或者無效指標解引用 4 引用已經釋放的記憶體 未定義 例如 for p head p null p p next free p 可以寫成 for p head p null p q 5 對同一塊記憶體釋放多次...