久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

內(nèi)存報(bào)錯:corruption,,Cannot allocate memory

 海漩渦 2016-05-11

前段時間開發(fā)的一個后端C模塊上線后,,線上出core,初始時,,因?yàn)樵L問壓力不大,,所以崩潰是上線3天左右出現(xiàn)的。當(dāng)時用gdb跟進(jìn)調(diào)用堆棧并檢查源代碼,,發(fā)現(xiàn)出core位置的代碼沒有啥問題,。因?yàn)楫?dāng)時開發(fā)任務(wù)較重,且該模塊不保存狀態(tài)(崩潰重新啟動不影響對外服務(wù)),,所以沒有深入跟進(jìn),。后來隨著client版本號逐漸放量導(dǎo)致訪問壓力上升,,噩夢開始了。,。,。
該模塊會不定時core掉,并且差點(diǎn)兒每次崩潰時的調(diào)用堆棧都不一樣,,關(guān)鍵是最后幾層堆棧非常多都位于差點(diǎn)兒不可能出問題的代碼中,,比方庫函數(shù)或廠里的公共庫。
好在在眾多core文件里發(fā)現(xiàn)規(guī)律:每次基本都是在對內(nèi)存動態(tài)操作時掛掉,,比方malloc/realloc/free/new/delete都引起了崩潰,。并且幸運(yùn)的是,崩潰進(jìn)程還是輸出了一些關(guān)鍵信息,,比方以下這些(這些是在不同的崩潰時刻分別輸出的):
*** glibc detected *** malloc(): memory corruption: 0x0000002a95c1ff10 ***
*** glibc detected *** double free or corruption (out): 0x0000000000f0d910 ***
*** glibc detected *** free(): invalid next size (normal): 0x0000002a96103b00 ***
*** glibc detected *** free(): invalid next size (fast): 0x0000000000f349d0 ***
*** glibc detected *** corrupted double-linked list: 0x0000002a95f062e0 ***
從上面的日志也能夠看到,,每次引起崩潰的直接原因都可能不同。用gdb又細(xì)致查看core文件發(fā)現(xiàn),,有時進(jìn)程是收到SIGABRT信號后退出,有時又是收到SIGSEGV信號后退出,。
由此,,基本定位了崩潰原因:內(nèi)存訪問越界導(dǎo)致破壞了heap的數(shù)據(jù)結(jié)構(gòu)。用valgrind在線下環(huán)境啟動進(jìn)程,,試圖重現(xiàn)崩潰或定位越界訪問的代碼,,遺憾的是,腳本壓了1個小時也沒出現(xiàn)崩潰,,而valgrind的輸出報(bào)告也沒有越界代碼位置的提示,。
終于,細(xì)致檢查源代碼后發(fā)現(xiàn),,在某個回調(diào)函數(shù)中,,new出來的buffer接收完通過http post方式發(fā)送過來的2進(jìn)制數(shù)據(jù)后,我又多寫了1行代碼,,相似于:recv_buf[data_len] = '\0',,導(dǎo)致越界多寫1個字節(jié),終于引起各種莫名其妙的內(nèi)存崩潰,。
經(jīng)驗(yàn)教訓(xùn):
1)調(diào)用堆棧信息對定位問題幫助非常大,,但也不可盡信。比方這次遇到的情況,,每次出core的調(diào)用堆棧差點(diǎn)兒都不一樣,,并且最后幾層棧幀都是不可能出現(xiàn)故障的庫函數(shù)或久經(jīng)考驗(yàn)的公司公共庫,這樣的情況下,,思維須要跳出局部,,在更高的層次尋找規(guī)律或原因
2)一旦定位崩潰屬于堆內(nèi)存讀寫越界問題,,就細(xì)致檢查自己的代碼吧,因?yàn)閹旌瘮?shù)或公共庫出問題的概率太小了,,所以不要存在僥幸心理,,這個時候,盲目的自信要不得
3)本來自覺得對內(nèi)存操作已經(jīng)非常小心了,,沒想到還是在想當(dāng)然的瞬間寫下犯錯的代碼,,導(dǎo)致終于花費(fèi)非常多時間和精力去“捉蟲”。只是好在跟進(jìn)崩潰的過程中添加了一點(diǎn)分析/定位問題的經(jīng)驗(yàn),,也算有些收獲吧

=============== EOF =================




====================================================
1,、
一次申請超過剩余內(nèi)存大小,會“Cannot allocate memory”

但是多次申請內(nèi)存,,總量大于內(nèi)存總大小卻沒有報(bào)錯,??,?,??


2,、一次申請的內(nèi)存,,在不使用的情況下,free,、top查看內(nèi)存情況無變化


3,、將內(nèi)存memset清零時,free,、top查看內(nèi)存減少申請的大小



================================================================


昨天在修改自己的代碼的時候,,碰到了malloc函數(shù)內(nèi)存分配失敗,上網(wǎng)翻了翻,,一個很可能的原因是之前的代碼出現(xiàn)了越界操作,,導(dǎo)致malloc分配函數(shù)所涉及的一些信息被破壞。在這個思想的指導(dǎo)下,,今天又是郁悶了一整天,,來來回回看自己的代碼。又加不斷的調(diào)試,,終于發(fā)現(xiàn)自己的代碼中有一個malloc分配的內(nèi)存大小為0,,不是自己預(yù)想的大小,而之后的代碼又按預(yù)想的大小對內(nèi)存進(jìn)行了操作,,導(dǎo)致了下一個malloc無法分配內(nèi)存,。
總結(jié)自己的問題,如果下一次再碰到這樣的問題,,就要查從不能分配的那個malloc函數(shù)開始往回找最近的那個能分配的malloc,,出問題的代碼應(yīng)該就在這部分,,很可能的原因就是指針越界,對未知的內(nèi)存進(jìn)行了操作,,導(dǎo)致了malloc不能繼續(xù)分配內(nèi)存,。


=================================================================


以前分配的比這還大不代表你這次分配大內(nèi)存就能成功。分配成功的前提是你進(jìn)程內(nèi)部有足夠大的連續(xù)可用的內(nèi)存
注意:前提有兩個,,第一是可用,,第二還必須“連續(xù)”
也就是說,要是你進(jìn)程內(nèi)沒有一塊內(nèi)存大于你要求的尺寸,,分配就失敗


=============================================================

在C語言中, 執(zhí)行到malloc程序core的時候, 一般人的第一反應(yīng)是內(nèi)存空間不足. 常見的代碼為:

  1. #define SIZE 100  
  2. int* p = (int*)malloc(SIZE * sizeof(int));  
但是, 事實(shí)情況是: 內(nèi)存還多的很.

有的C編譯器對沒有聲明的函數(shù), 是不報(bào)錯的(有的連警告都沒有, C編譯器認(rèn)為程序員永遠(yuǎn)是正確的). 糟糕的是, C編譯器默認(rèn)認(rèn)為函數(shù)的返回值是int類型. 如果沒有加以下頭文件的話:

  1. #include <stdlib.h>  

程序把malloc的返回值強(qiáng)轉(zhuǎn)成int, 然后再轉(zhuǎn)成int*. 于是程序core了.



==============================================================


最近在代碼調(diào)試過程中發(fā)現(xiàn)一很無解的bug,,跟蹤到代碼發(fā)現(xiàn)malloc()函數(shù)總是申請空間失敗,返回0地址,。這類bug往往很難定位,,因?yàn)榍懊孢\(yùn)行正常不出錯。經(jīng)過仔細(xì)琢磨發(fā)現(xiàn)問題出現(xiàn)在malloc()函數(shù)前面的代碼中,,如果前面代碼使用到memset或者memcpy等類似函數(shù),,并且在使用過程中發(fā)生地址越界,則可能導(dǎo)致后面的malloc申請空間失敗,,所以此時應(yīng)檢測前面的代碼,。

別人已經(jīng)提到的類似例子:

#include <stdlib.h>
#include 
<stdio.h>
#include 
<memory.h>

int main()
{
    #define BUF_SIZE 25

    _asm 
int 3;
    
char* lpszBuf = (char*)malloc(BUF_SIZE);
    memset(lpszBuf, 
0x00, BUF_SIZE*2);
    
char* lpszTest = (char*)malloc(BUF_SIZE); // <==== 內(nèi)存分配失敗
    free(lpszBuf);                            // <==== 出錯 執(zhí)行到 int 3; 指令
    free(lpszTest);

    
return 0;
}


==============================================================


malloc失敗情況

1、堆空間被越界的操作或整理操作破壞了
memset,、*指針賦值

2、內(nèi)存碎片多,,沒有一塊連續(xù)的內(nèi)存適合申請的大小,,即使內(nèi)存剩余總量大于需要申請的大小也會失敗。


3,、在C語言中, 執(zhí)行到malloc程序core的時候, 一般人的第一反應(yīng)是內(nèi)存空間不足. 常見的代碼為:

  1. #define SIZE 100  
  2. int* p = (int*)malloc(SIZE * sizeof(int));  
但是, 事實(shí)情況是: 內(nèi)存還多的很.

有的C編譯器對沒有聲明的函數(shù), 是不報(bào)錯的(有的連警告都沒有, C編譯器認(rèn)為程序員永遠(yuǎn)是正確的). 糟糕的是, C編譯器默認(rèn)認(rèn)為函數(shù)的返回值是int類型. 如果沒有加以下頭文件的話:

  1. #include <stdlib.h>  

程序把malloc的返回值強(qiáng)轉(zhuǎn)成int, 然后再轉(zhuǎn)成int*. 于是程序core了.



    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn),。請注意甄別內(nèi)容中的聯(lián)系方式,、誘導(dǎo)購買等信息,謹(jǐn)防詐騙,。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,,請點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多