double free 記憶體問題

2021-05-22 14:18:56 字數 2504 閱讀 9585

double free

2023年06月02日 星期一 11:43

*** glibc detected *** free(): invalid pointer:

*** glibc detected *** malloc(): memory corruption:

*** glibc detected *** double free or corruption (out): 0x00000000005c18a0 ***

*** glibc detected *** corrupted double-linked list: 0x00000000005ab150 ***

你是否遇到過這樣的情況,太沮喪了,程式總是無端coredump,gdb到core檔案裡面也看不出個所以然來,這對於乙個大型的商業系統來說太令人恐怖了,事故隨時可能發生。

遇到棘手的問題,慌張是沒用的,解決不了任何問題。先坐下來,喝杯茶,舒緩一下神經。

記憶體問題始終是c++程式設計師需要去面對的問題,這也是c++語言的門檻較高的原因之一。通常我們會犯的記憶體問題大概有以下幾種:

1.記憶體重複釋放,出現double free時,通常是由於這種情況所致。

2.記憶體洩露,分配的記憶體忘了釋放。

3.記憶體越界使用,使用了不該使用的記憶體。

4.使用了無效指標。

5.空指標,對乙個空指標進行操作。

對於第一種和第二種,第五種情況,就不用多說,會產生什麼後果大家應該都很清楚。

第四種情況,通常是指操作已釋放的物件,如:

1.已釋放物件,卻再次操作該指標所指物件。

2.多執行緒中某一動態分配的物件同時被兩個執行緒使用,乙個執行緒釋放了該物件,而另一線程繼續對該物件進行操作。

我們重點**第三種情況,相對於另幾種情況,這可以稱得上是疑難雜症了(第四種情況也可以理解成記憶體越界使用)。

記憶體越界使用,這樣的錯誤引起的問題存在極大的不確定性,有時大,有時小,有時可能不會對程式的執行產生影響,正是這種不易重現的錯誤,才是最致命的,一旦出錯破壞性極大。

什麼原因會造成記憶體越界使用呢?有以下幾種情況,可供參考:

例1:

char buf[32] = ;

for(int i=0; i32

....

例2:

char buf[32] = ;

string str = "this is a test sting !!!!";

sprintf(buf, "this is a test buf!string:%s", str.c_str()); //out of buffer space

....

例3:

string str = "this is a test string!!!!";

char buf[16] = ;

strcpy(buf, str.c_str()); //out of buffer space

類似的還存在隱患的函式還有:

strcat,vsprintf等

同樣,memcpy, memset, memmove等一些記憶體操作函式在使用時也一定要注意。

當這樣的**一旦執行,錯誤就在所難免,會帶來的後果也是不確定的,通常可能會造成如下後果:

1.破壞了堆中的記憶體分配資訊資料,特別是動態分配的記憶體塊的記憶體資訊資料,因為作業系統在分配和釋放記憶體塊時需要訪問該資料,一旦該資料被破壞,以下的幾種情況都可能會出現。

*** glibc detected *** free(): invalid pointer:

*** glibc detected *** malloc(): memory corruption:

*** glibc detected *** double free or corruption (out): 0x00000000005c18a0 ***

*** glibc detected *** corrupted double-linked list: 0x00000000005ab150 ***       

2.破壞了程式自己的其他物件的記憶體空間,這種破壞會影響程式執行的不正確性,當然也會誘發coredump,如破壞了指標資料。

3.破壞了空閒記憶體塊,很幸運,這樣不會產生什麼問題,但誰知道什麼時候不幸會降臨呢?

通常,**錯誤被激發也是偶然的,也就是說之前你的程式一直正常,可能由於你為類增加了兩個成員變數,或者改變了某一部分**,coredump就頻繁發生,而你增加的**絕不會有任何問題,這時你就應該考慮是否是某些記憶體被破壞了。

排查的原則,首先是保證能重現錯誤,根據錯誤估計可能的環節,逐步裁減**,縮小排查空間。

檢查所有的記憶體操作函式,檢查記憶體越界的可能。常用的記憶體操作函式:

sprintf snprintf

vsprintf vsnprintf

strcpy strncpy strcat

memcpy memmove memset bcopy

如果有用到自己編寫的動態庫的情況,要確保動態庫的編譯與程式編譯的環境一致。

保持好的編碼習慣是杜絕錯誤的最好方式!

記憶體對齊問題

一直困惑自己有兩個問題 1.程式為什麼要做記憶體對齊?1.處理器訪問記憶體是粒度為多位元組時,如果資料不是在邊界處,則,處理器需要分多個時鐘週期進行資料的訪問。2.增加可移植性。並非所有的處理器都可以訪問任何位址,可能出現硬體錯誤。具體可以參考 2.struct中如何計算記憶體對齊?先說說c語言中s...

記憶體對齊問題

首先由乙個程式引入話題 1 環境 vc6 windows sp22 程式13 include iostream 45 using namespace std 67 struct st1 8 1314 struct st215 20 21int main 2227 程式的輸出結果為 sizeof st...

記憶體對齊問題

一 什麼是位元組對齊,為什麼要對齊?現代計算機中記憶體空間都是按照byte劃分的,從理論上講似乎對任何型別的變數的訪問可以從任何位址開始,但實際情況是在訪問特定型別變數的時候經常在特定的記憶體位址訪問,這就需要各種型別資料按照一定的規則在空間上排列,而不是順序的乙個接乙個的排放,這就是對齊。對齊的作...