在嵌入式開發中,經常會使用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...