溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

如何實(shí)現(xiàn)IAR中使用堆和棧的問題分析

發(fā)布時(shí)間:2022-01-06 15:22:40 來源:億速云 閱讀:593 作者:柒染 欄目:互聯(lián)網(wǎng)科技

這期內(nèi)容當(dāng)中小編將會(huì)給大家?guī)碛嘘P(guān)如何實(shí)現(xiàn)IAR中使用堆和棧的問題分析,文章內(nèi)容豐富且以專業(yè)的角度為大家分析和敘述,閱讀完這篇文章希望大家可以有所收獲。

堆是什么?

堆是內(nèi)存空間里為動(dòng)態(tài)內(nèi)存分配保留的一部分區(qū)域

當(dāng)一個(gè)應(yīng)用需要臨時(shí)使用一定數(shù)量的內(nèi)存時(shí)可以從堆空間分配或借用,C中通過調(diào)用malloc()函數(shù)實(shí)現(xiàn),C++中通過’new’來實(shí)現(xiàn)

當(dāng)這個(gè)內(nèi)存不再需要時(shí)可以通過調(diào)用free()函數(shù)或者使用delet操作符來釋放。一旦該內(nèi)存被釋放,可以再次分配使用。

堆的位置和大小是在編譯時(shí)靜態(tài)設(shè)置的。

為你的應(yīng)用分配合適的堆空間很重要,否則在運(yùn)行時(shí)可能崩潰。

怎樣決定堆大小

考慮應(yīng)用使用的動(dòng)態(tài)內(nèi)存時(shí)的首要問題是我需要多少堆空間?

    相比來說這更像是估計(jì)而不是計(jì)算

    如果你知道你的應(yīng)用怎樣行動(dòng),那么你應(yīng)該大概知道每個(gè)時(shí)刻應(yīng)該分配多少內(nèi)存

另外需要考慮在管理堆空間是有一些額外的開銷

    堆管理器需要跟蹤已經(jīng)使用的和剩余的空間數(shù)量,已經(jīng)分配了的塊大小,通常還包含一個(gè)指向下一個(gè)可用內(nèi)存的指針

    另外,開發(fā)工具可能為了維護(hù)內(nèi)存體系結(jié)構(gòu)保留一定的內(nèi)存塊。譬如,EWARM編譯器通常為保證棧對(duì)齊而保留8字節(jié)倍數(shù)的內(nèi)存塊。

潛在的問題

當(dāng)不同規(guī)模的內(nèi)存塊頻繁分配、釋放時(shí),動(dòng)態(tài)內(nèi)存分配是最常發(fā)生的問題隨之而來。

    當(dāng)內(nèi)存釋放時(shí),就會(huì)有一個(gè)空位

    如果下一個(gè)要分配的空間比所有的空位都要大,這就會(huì)是個(gè)問題

    這為debugging帶來困難,因?yàn)槎焉峡偟目臻e內(nèi)存空間比要分配的要大,但是內(nèi)存申請(qǐng)可鞥因?yàn)榭臻e空間不連續(xù)而失敗。

    例如,假設(shè)如下:

        堆的位置為0x20000-0x20FFF

        一個(gè)8字節(jié)的內(nèi)存塊分布在該區(qū)間的開始位置

        緊接著是一個(gè)1024字節(jié)的塊

    之后,第一個(gè)塊被釋放并可以再次使用。然而,應(yīng)用需要分配大于8字節(jié)的空間,所以開始 的8字節(jié)空間就無法使用。這就是內(nèi)存碎片化,如果應(yīng)用用于不在需要8字節(jié)或更少的內(nèi)存空間,那么這8字節(jié)的內(nèi)存空間就浪費(fèi)了。這個(gè)例子也說明了為什么堆中的小內(nèi)存塊是低效的,這種開銷等于應(yīng)用可用數(shù)據(jù)的數(shù)量。

如何實(shí)現(xiàn)IAR中使用堆和棧的問題分析

堆的布局

    有些情況下確切的知道堆上有些什么,位于什么位置是非常有用的。

    堆上包含的不只是分派的數(shù)據(jù):

        有一些維護(hù)堆的額外開銷

        每一個(gè)分配的內(nèi)存塊都包含兩個(gè)整數(shù),指針的大小取決于CPU的架構(gòu),e.g. ARM器件會(huì)使用32bit的整數(shù)。

            第一個(gè)整數(shù)指明分派的內(nèi)存塊的大小。

            最后一個(gè)堆對(duì)象后會(huì)有一個(gè)32bit的值來說明剩余的堆空間。

            最后一個(gè)堆對(duì)象開始位置的32bit值說明這個(gè)數(shù)據(jù)的地址。

    堆同時(shí)跟蹤下一個(gè)分配的位置,使用一個(gè)駐留在堆外部的結(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 說明下一個(gè)可用分配的內(nèi)存地址。如果堆空間耗盡,_Next指針則為NULL。

堆的最終思考

如果沒有一些工具輔助你分析動(dòng)態(tài)內(nèi)存需求,直接估計(jì)堆空間是比較困難的。

        在桌面Java中有這樣的工具(HAT,Heap Analysis Tool)

        嵌入式C/C++中還沒有類似工具

針對(duì)資源有限的嵌入式系統(tǒng),由于額外的開銷和可能的堆內(nèi)存碎片化,動(dòng)態(tài)內(nèi)存應(yīng)該盡量少用。

        在你的代碼中(測(cè)試用例中)你可以創(chuàng)建多個(gè)結(jié)構(gòu)體或者對(duì)象

        MISRA C要求所有內(nèi)存都必須在編譯時(shí)靜態(tài)分配,因此你永遠(yuǎn)也不會(huì)跑出堆空間。

EWARM中的堆統(tǒng)計(jì)

EWARM中的C-Spy debugger讓你可以看到當(dāng)前堆的使用情況

要看到這個(gè)功能,必須在工程中包含 dlmalloc.c

調(diào)用 __iar_dlmallinfo() 和 __iar_dlmalloc_stats() 會(huì)在Terminal I/O窗口打印堆統(tǒng)計(jì)情況。

如何實(shí)現(xiàn)IAR中使用堆和棧的問題分析

4.如果給定太大的??臻g,RAM就浪費(fèi)了,如果給定的??臻g太小,會(huì)出現(xiàn)兩種情況(取決于棧在內(nèi)存空間的位置):

    a 變量會(huì)被改寫,導(dǎo)致未定義的行為

    b 棧會(huì)超出內(nèi)存空間,導(dǎo)致應(yīng)用的異常終止

因?yàn)榈诙N選擇比較用于檢測(cè)到,你應(yīng)該考慮將棧設(shè)置為朝內(nèi)存重點(diǎn)增長(zhǎng)。

靜態(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包含一個(gè)易用的棧插件,可以監(jiān)控CSTACK的大小,同時(shí)如果你超出指定的棧門限將輸出消息到debug日志。

警告:該插件對(duì)于RTOS是無效的,使用RTOS時(shí)他始終匯報(bào)堆棧溢出。

上述就是小編為大家分享的如何實(shí)現(xiàn)IAR中使用堆和棧的問題分析了,如果剛好有類似的疑惑,不妨參照上述分析進(jìn)行理解。如果想知道更多相關(guān)知識(shí),歡迎關(guān)注億速云行業(yè)資訊頻道。

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

iar
AI