這期內(nèi)容當(dāng)中小編將會給大家?guī)碛嘘P(guān)如何實現(xiàn)IAR中使用堆和棧的問題分析,文章內(nèi)容豐富且以專業(yè)的角度為大家分析和敘述,閱讀完這篇文章希望大家可以有所收獲。
創(chuàng)新互聯(lián)主要從事成都網(wǎng)站設(shè)計、成都網(wǎng)站制作、網(wǎng)頁設(shè)計、企業(yè)做網(wǎng)站、公司建網(wǎng)站等業(yè)務(wù)。立足成都服務(wù)通川,10余年網(wǎng)站建設(shè)經(jīng)驗,價格優(yōu)惠、服務(wù)專業(yè),歡迎來電咨詢建站服務(wù):18980820575
堆是什么?
堆是內(nèi)存空間里為動態(tài)內(nèi)存分配保留的一部分區(qū)域
當(dāng)一個應(yīng)用需要臨時使用一定數(shù)量的內(nèi)存時可以從堆空間分配或借用,C中通過調(diào)用malloc()函數(shù)實現(xiàn),C++中通過’new’來實現(xiàn)
當(dāng)這個內(nèi)存不再需要時可以通過調(diào)用free()函數(shù)或者使用delet操作符來釋放。一旦該內(nèi)存被釋放,可以再次分配使用。
堆的位置和大小是在編譯時靜態(tài)設(shè)置的。
為你的應(yīng)用分配合適的堆空間很重要,否則在運行時可能崩潰。
怎樣決定堆大小
考慮應(yīng)用使用的動態(tài)內(nèi)存時的首要問題是我需要多少堆空間?
相比來說這更像是估計而不是計算
如果你知道你的應(yīng)用怎樣行動,那么你應(yīng)該大概知道每個時刻應(yīng)該分配多少內(nèi)存
另外需要考慮在管理堆空間是有一些額外的開銷
堆管理器需要跟蹤已經(jīng)使用的和剩余的空間數(shù)量,已經(jīng)分配了的塊大小,通常還包含一個指向下一個可用內(nèi)存的指針
另外,開發(fā)工具可能為了維護內(nèi)存體系結(jié)構(gòu)保留一定的內(nèi)存塊。譬如,EWARM編譯器通常為保證棧對齊而保留8字節(jié)倍數(shù)的內(nèi)存塊。
潛在的問題
當(dāng)不同規(guī)模的內(nèi)存塊頻繁分配、釋放時,動態(tài)內(nèi)存分配是最常發(fā)生的問題隨之而來。
當(dāng)內(nèi)存釋放時,就會有一個空位
如果下一個要分配的空間比所有的空位都要大,這就會是個問題
這為debugging帶來困難,因為堆上總的空閑內(nèi)存空間比要分配的要大,但是內(nèi)存申請可鞥因為空閑空間不連續(xù)而失敗。
例如,假設(shè)如下:
堆的位置為0x20000-0x20FFF
一個8字節(jié)的內(nèi)存塊分布在該區(qū)間的開始位置
緊接著是一個1024字節(jié)的塊
之后,第一個塊被釋放并可以再次使用。然而,應(yīng)用需要分配大于8字節(jié)的空間,所以開始 的8字節(jié)空間就無法使用。這就是內(nèi)存碎片化,如果應(yīng)用用于不在需要8字節(jié)或更少的內(nèi)存空間,那么這8字節(jié)的內(nèi)存空間就浪費了。這個例子也說明了為什么堆中的小內(nèi)存塊是低效的,這種開銷等于應(yīng)用可用數(shù)據(jù)的數(shù)量。
堆的布局
有些情況下確切的知道堆上有些什么,位于什么位置是非常有用的。
堆上包含的不只是分派的數(shù)據(jù):
有一些維護堆的額外開銷
每一個分配的內(nèi)存塊都包含兩個整數(shù),指針的大小取決于CPU的架構(gòu),e.g. ARM器件會使用32bit的整數(shù)。
第一個整數(shù)指明分派的內(nèi)存塊的大小。
最后一個堆對象后會有一個32bit的值來說明剩余的堆空間。
最后一個堆對象開始位置的32bit值說明這個數(shù)據(jù)的地址。
堆同時跟蹤下一個分配的位置,使用一個駐留在堆外部的結(jié)構(gòu)體中。
typedef struct {
__data_Cell __data * __data *_Plast;
__data_Cell __data *_Head; }
__data_Altab;
指針_Head說明堆的當(dāng)前狀態(tài)。指針_Plast說明從哪里開始搜索目前未使用的可用塊。
__data_Cell結(jié)構(gòu)體定義如下:
typedef struct __data_Cell
{
__data_size_t _Size;
struct __data_Cell __data *_Next;
} __data_Cell;
其中_Size 說明堆的剩余數(shù)量, _Next 說明下一個可用分配的內(nèi)存地址。如果堆空間耗盡,_Next指針則為NULL。
堆的最終思考
如果沒有一些工具輔助你分析動態(tài)內(nèi)存需求,直接估計堆空間是比較困難的。
在桌面Java中有這樣的工具(HAT,Heap Analysis Tool)
嵌入式C/C++中還沒有類似工具
針對資源有限的嵌入式系統(tǒng),由于額外的開銷和可能的堆內(nèi)存碎片化,動態(tài)內(nèi)存應(yīng)該盡量少用。
在你的代碼中(測試用例中)你可以創(chuàng)建多個結(jié)構(gòu)體或者對象
MISRA C要求所有內(nèi)存都必須在編譯時靜態(tài)分配,因此你永遠也不會跑出堆空間。
EWARM中的堆統(tǒng)計
EWARM中的C-Spy debugger讓你可以看到當(dāng)前堆的使用情況
要看到這個功能,必須在工程中包含 dlmalloc.c
調(diào)用 __iar_dlmallinfo() 和 __iar_dlmalloc_stats() 會在Terminal I/O窗口打印堆統(tǒng)計情況。
4.如果給定太大的棧空間,RAM就浪費了,如果給定的??臻g太小,會出現(xiàn)兩種情況(取決于棧在內(nèi)存空間的位置):
a 變量會被改寫,導(dǎo)致未定義的行為
b 棧會超出內(nèi)存空間,導(dǎo)致應(yīng)用的異常終止
因為第二種選擇比較用于檢測到,你應(yīng)該考慮將棧設(shè)置為朝內(nèi)存重點增長。
靜態(tài)棧檢查器
有很多靜態(tài)的C語言檢查器
Express Logic’s StackX
Abslnt’s StackAnalyzer
John Regher’s Stack Analysis(for AVR/430 only)
AdaCore’s GNATStack
Embedded Workbench’s Stack Plug-in
EW包含一個易用的棧插件,可以監(jiān)控CSTACK的大小,同時如果你超出指定的棧門限將輸出消息到debug日志。
警告:該插件對于RTOS是無效的,使用RTOS時他始終匯報堆棧溢出。
上述就是小編為大家分享的如何實現(xiàn)IAR中使用堆和棧的問題分析了,如果剛好有類似的疑惑,不妨參照上述分析進行理解。如果想知道更多相關(guān)知識,歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道。