【轉(zhuǎn):http://blog.csdn.net/wclin88/article/details/7276972】
*** 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文件里面也看不出個所以然來,這對于一個大型的商業(yè)系統(tǒng)來說太令人恐怖了,事故隨時可能發(fā)生。
遇到棘手的問題,慌張是沒用的,解決不了任何問題。先坐下來,喝杯茶,舒緩一下神經(jīng)。
內(nèi)存問題始終是c++程序員需要去面對的問題,這也是c++語言的門檻較高的原因之一。通常我們會犯的內(nèi)存問題大概有以下幾種:
- 內(nèi)存重復釋放,出現(xiàn)double free時,通常是由于這種情況所致。
- 內(nèi)存泄露,分配的內(nèi)存忘了釋放。
- 內(nèi)存越界使用,使用了不該使用的內(nèi)存。
- 使用了無效指針。
- 空指針,對一個空指針進行操作。
對于第一種和第二種,第五種情況,就不用多說,會產(chǎn)生什么后果大家應(yīng)該都很清楚。
第四種情況,通常是指操作已釋放的對象,如:
- 已釋放對象,卻再次操作該指針所指對象。
- 多線程中某一動態(tài)分配的對象同時被兩個線程使用,一個線程釋放了該對象,而另一線程繼續(xù)對該對象進行操作。
我們重點探討第三種情況,相對于另幾種情況,這可以稱得上是疑難雜癥了(第四種情況也可以理解成內(nèi)存越界使用)。
內(nèi)存越界使用,這樣的錯誤引起的問題存在極大的不確定性,有時大,有時小,有時可能不會對程序的運行產(chǎn)生影響,正是這種不易重現(xiàn)的錯誤,才是最致命的,一旦出錯破壞性極大。
什么原因會造成內(nèi)存越界使用呢?有以下幾種情況,可供參考:
例1:
char buf[32] = {0};
for(int i=0; i<n; i++)// n < 32 or n > 32
{
buf[i] = 'x';
}
....
例2:
char buf[32] = {0};
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] = {0};
strcpy(buf, str.c_str()); //out of buffer space
類似的還存在隱患的函數(shù)還有:
strcat,vsprintf等
同樣,memcpy, memset, memmove等一些內(nèi)存操作函數(shù)在使用時也一定要注意。
當這樣的代碼一旦運行,錯誤就在所難免,會帶來的后果也是不確定的,通??赡軙斐扇缦潞蠊?/p>
破壞了堆中的內(nèi)存分配信息數(shù)據(jù),特別是動態(tài)分配的內(nèi)存塊的內(nèi)存信息數(shù)據(jù),因為操作系統(tǒng)在分配和釋放內(nèi)存塊時需要訪問該數(shù)據(jù),一旦該數(shù)據(jù)被破壞,以下的幾種情況都可能會出現(xiàn)。
*** 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 ***破壞了程序自己的其他對象的內(nèi)存空間,這種破壞會影響程序執(zhí)行的不正確性,當然也會誘發(fā)coredump,如破壞了指針數(shù)據(jù)。
破壞了空閑內(nèi)存塊,很幸運,這樣不會產(chǎn)生什么問題,但誰知道什么時候不幸會降臨呢?
通常,代碼錯誤被激發(fā)也是偶然的,也就是說之前你的程序一直正常,可能由于你為類增加了兩個成員變量,或者改變了某一部分代碼,coredump就頻繁發(fā)生,而你增加的代碼絕不會有任何問題,這時你就應(yīng)該考慮是否是某些內(nèi)存被破壞了。
排查的原則,首先是保證能重現(xiàn)錯誤,根據(jù)錯誤估計可能的環(huán)節(jié),逐步裁減代碼,縮小排查空間。
檢查所有的內(nèi)存操作函數(shù),檢查內(nèi)存越界的可能。常用的內(nèi)存操作函數(shù):
sprintf snprintf
vsprintf vsnprintf
strcpy strncpy strcat
memcpy memmove memset bcopy
如果有用到自己編寫的動態(tài)庫的情況,要確保動態(tài)庫的編譯與程序編譯的環(huán)境一致。