嵌入式中的malloc記憶體洩漏問題排查技巧

2021-10-06 02:50:57 字數 2009 閱讀 8802

在嵌入式開發中,經常會使用malloc,free分配釋放堆記憶體,稍不小心就可能導致記憶體一點點地洩露,直至堆記憶體洩露完,導致裝置異常重啟或宕機現象時,才追悔莫及。rtos環境沒有什麼有效的除錯工具,下面分享一種記憶體洩漏定位排查技巧。

#define mutex_lock     				

//自行移植,互斥鎖

#define mutex_unlock

#define malloc_size_offset 16

volatile

int gusedbytes=0;

//統計已使用記憶體位元組數

volatile

int gcalledtimes=0;

//統計未釋放次數

封裝malloc函式:

void

*sys_malloc

(int size)

mutex_unlock;

return p;

}

封裝calloc:

void

*sys_calloc

(int nums,

int size)

mutex_unlock;

return p;

}

封裝free函式:

void

sys_free

(void

* paddr)

mutex_lock;

plen =

(int*)

((int)paddr-malloc_size_offset)

;//位址前移到長度字段

gusedbytes -=(

*plen)

;

gcalledtimes--

;//次數-1

mutex_unlock;

}

獲取堆記憶體已使用位元組數,及未釋放的次數:

void

sys_getstatus

(int

* usedmem,

int* nofreetimes)

參考下圖所示,開啟編譯器記憶體偵錯程式或者進行記憶體列印,下圖是vc6除錯環境,malloc會返回乙個記憶體位址p,將p前面的30個位元組列印出來,下圖我申請了256個位元組(0x100),可以看出偏移了16個位元組,故而將malloc_size_offset巨集定義為16,這個偏移量是與編譯器強相關的,自行結合cpu和編譯器確認,目前筆者能確定的是,vc6是偏移16個位元組,keil(stm32 mcu)偏移是4個位元組。

在開發除錯的過程中,可以每隔10秒呼叫1次void sys_getstatus(int* usedmem,int* nofreetimes)函式,將記憶體佔用量及未釋放次數列印出來,用來觀測有無記憶體洩漏情況。

void

thread1

(void

)osdelay(1

);}}

當定位到是哪個執行緒後,可以依此類推,繼續縮小定位**範圍,直至發現洩漏位置。裸機開發也是如此。

最常見的是純粹的忘記free釋放;另外一種就很可怕,指標位址被改變了,再去free就可能會改變malloc內部的變數,導致異常,如下圖所示,p+=100了3次,再去free就很有問題。這種情況也可以通過sys_getstatus(int* usedmem,int* nofreetimes)來發現,usedmem值會異常,可能為負值,但是nofreetimes未釋放次數是正常的。

另外如果允許的情況下,裝置可以凌晨定期重啟一次,來保證裝置的穩定執行(可以緩解洩漏和碎片問題)。

void

test

(void

)free

(p);

}

嵌入式記憶體布局

從事手機平台研發也有一年多了,總結了一下有關手機記憶體方面的知識希望對新手有所裨益。如果有高手路過檢視之餘如有紕漏之處還請不吝賜教 說明 傳統 燒機 流程將軟體燒錄到flash中,軟體bootloader部分在nor flash中,軟體的其他部分燒錄到nand flash 強調一點 上圖左邊部分是f...

嵌入式系統 記憶體管理

教材 嵌入式系統及應用,羅蕾 李允 陳麗蓉等,電子工業出版社 嵌入式實時作業系統在記憶體管理方面需要考慮如下因素 快速而確定的記憶體管理 通常的作業系統都至少具有基本的記憶體管理方法 提供記憶體分配與釋放的系統呼叫 不使用虛擬儲存技術 在嵌入式實時作業系統中一般不使用虛擬儲存技術,以避免頁面置換所帶...

嵌入式 記憶體分配管理

嵌入式 記憶體分配管理 嵌入式的記憶體一般都非常的小,最進在學習lwip協議棧的移植,在正點原子的學習資料中找到了許多關於怎麼移植協議棧的東西,其中使用到了記憶體的分配管理技術,能夠高效的管理和使用記憶體,學習之後整理了放在這裡。一 記憶體分配管理函式 函式名函式說說明 輸入 輸出 memory i...