<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          在嵌入式中,如何正確使用動態(tài)內(nèi)存?

          共 5985字,需瀏覽 12分鐘

           ·

          2022-01-19 11:33

          ????關(guān)注、星標(biāo)公眾號,直達(dá)精彩內(nèi)容

          來源:jiangjunjie_2005


          一. ?常見錯(cuò)誤與預(yù)防

          1. ? 分配后忘記釋放內(nèi)存

          void?func(void)
          {
          ????p?=?malloc(len);
          ????do_something(p);
          ????return;??/*錯(cuò)誤!退出程序時(shí)沒有釋放內(nèi)存*/
          }

          預(yù)防:?編寫代碼時(shí)malloc()和free()保證成對出現(xiàn),避免忘記資源回收。

          int?func(void)
          {
          ????p?=?malloc(len);
          ????if?(condition)
          ????????return?-1;??/*錯(cuò)誤!退出程序時(shí)沒有釋放內(nèi)存*/
          ????free(p);
          ????return?0;
          }

          預(yù)防:?一旦使用動態(tài)內(nèi)存分配,請仔細(xì)檢查程序的退出分支是否已經(jīng)釋放該動態(tài)內(nèi)存。

          2. ? 釋放內(nèi)存調(diào)用錯(cuò)誤指針

          void?func(void)
          {
          ????p?=?malloc(len);
          ????val?=?*p++;??/*錯(cuò)誤!動態(tài)內(nèi)存句柄不可移動*/
          ????free(p);
          }

          預(yù)防:?千萬不要修改動態(tài)內(nèi)存句柄!可以另外賦值給其他指針變量,再對該動態(tài)內(nèi)存進(jìn)行訪問操作。

          3. ? 分配內(nèi)存不夠?qū)е乱绯?/span>

          void?func(void)
          {
          ????len?=?strlen(str);
          ????p?=?malloc(len);
          ????strcpy(p,?str);??/*錯(cuò)誤!str的’\0’寫到動態(tài)內(nèi)存外*/
          }

          預(yù)防:?分配內(nèi)存前仔細(xì)思考長度是否足夠,千萬注意字符串拷貝占用內(nèi)存比字符串長度大1。

          二. ?自動查錯(cuò)機(jī)制

          盡管在開發(fā)過程中堅(jiān)守原則和謹(jǐn)慎編程甚至嚴(yán)格測試,然而內(nèi)存泄露的錯(cuò)誤還是難以杜絕,如何讓系統(tǒng)自動查出內(nèi)存泄露的錯(cuò)誤呢?

          一種比較好的方法是建立日志塊,即每次分配內(nèi)存時(shí)記錄該內(nèi)存塊的指針和大小,釋放時(shí)再去除該日志塊,如果有內(nèi)存泄露就會有對應(yīng)的日志塊記錄這些內(nèi)存沒有釋放,這樣就可以提醒程序員進(jìn)行查錯(cuò)。

          有了上述日志塊操作函數(shù),再來實(shí)現(xiàn)動態(tài)內(nèi)存分配與釋放函數(shù)就很容易了。只有當(dāng)處于DEBUG版本和打開內(nèi)存調(diào)試DMEM_DBG時(shí)才進(jìn)行日志登錄,否則MallocExt()和FreeExt()函數(shù)與malloc()和free()是等價(jià)的,這樣保證了系統(tǒng)處于發(fā)布版本時(shí)的性能。

          (代碼已經(jīng)過嚴(yán)格測試,但這不是盈利的商業(yè)代碼,即沒有版權(quán)。但如果因代碼錯(cuò)誤帶來的任何損失作者具有免責(zé)權(quán)利)

          代碼部分:

          首先定義日志塊結(jié)構(gòu)體:

          /*?Log?of?dynamic?memory?usage?*/
          typedef?struct?_dmem_log
          {

          ????struct?_dmem_log?*p_stNext;?/*?Point?to?next?log?*/
          ????const?void?*p_vDMem;?/*?Point?to?allocated?memory?by?this?pointer?*/
          ????INT32S?iSize;?/*?Size?of?the?allocated?memory?*/
          }?DMEM_LOG;

          然后為該結(jié)構(gòu)體開辟內(nèi)存:

          static?DMEM_LOG?*s_pstFreeLog;?/*?Point?to?free?log?pool?by?this?pointer?*/
          static?INT8U?s_byNumUsedLog;
          static?DMEM_LOG?*s_pstHeadLog;?/*?Point?to?used?log?chain?by?this?pointer?*/

          /*?Pool?of?dynamic?memory?log?*/
          #define?NUM_DMEM_LOG?20
          static?DMEM_LOG?s_astDMemLog[NUM_DMEM_LOG];

          下面是內(nèi)存日志塊的操作函數(shù):初始化、插入日志和移除日志:

          /**********************************************************?????????????????????????????????????????????????????????????*????????????????????Initialize?DMem?Log
          *?Description?:?Initialize?log?of?dynamic?memory
          *?Arguments??:?void
          *?Returns??????:?void
          *?Notes????????:
          **********************************************************/

          static?void?InitDMemLog(void)
          {
          ????INT16S????nCnt;
          ????/*?Initialize?pool?of?log?*/
          ????for?(nCnt?=?0;?nCnt?????{
          ????????/*?Point?to?next?one?*/
          ????????s_astDMemLog[nCnt].p_stNext?=?&s_astDMemLog[nCnt?+?1];
          ????}
          ????s_astDMemLog[NUM_DMEM_LOG?-?1].p_stNext?=?NULL;
          ????s_pstFreeLog?=?&s_astDMemLog[0];?/*?Point?to?the?1th?log?*/
          ????return;
          }

          /**********************************************************?????????????????????????????????????????????????????????????*???????????????????????Log?DMem
          *?Description?:?Join?an?allocated?memory?into?log?pool
          *?Arguments??:?const?void?*p_vAddr????point?to?address?of?this?allocated?memory?by?this?pointer
          *?????????????INT32S?iSize????size?of?this?allocated?memory
          *?Returns??????:?void
          *?Notes????????:
          **********************************************************/

          static?void?LogDMem(const?void?*p_vAddr,?INT32S?iSize)
          {
          ????ASSERT(p_vAddr?&&?iSize?>?0);
          ????DMEM_LOG?*p_stLog;
          ????#if?OS_CRITICAL_METHOD?==?3
          ????OS_CPU_SR??cpu_sr;
          ????#endif
          ????
          ????/*?Get?a?log?from?free?pool?*/
          ????OS_ENTER_CRITICAL();?/*?Avoid?race?condition?on?s_pstFreeLog?*/
          ????if?(!s_pstFreeLog)
          ????{
          ????????OS_EXIT_CRITICAL();
          ????????PRINTF("Allocate?DMemLog?failed.\r\n");???????
          ????????return;
          ????}
          ????p_stLog?=?s_pstFreeLog;
          ????s_pstFreeLog?=?s_pstFreeLog->p_stNext;
          ????OS_EXIT_CRITICAL();
          ????
          ????/*?Don't?need?to?protect?this?log?that?is?free?one?currently?*/
          ????p_stLog->p_vDMem?=?p_vAddr;
          ????p_stLog->iSize?=?iSize;

          ????/*?Put?this?log?into?used?chain?*/
          ????OS_ENTER_CRITICAL();?/*?Avoid?race?condition?*/
          ????p_stLog->p_stNext?=?s_pstHeadLog;
          ????s_pstHeadLog?=?p_stLog;
          ????++s_byNumUsedLog;
          ????OS_EXIT_CRITICAL();
          ????
          ????return;
          }

          /**********************************************************?????????????????????????????????????????????????????????????*???????????????????????Unlog?DMem
          *?Description?:?Remove?an?allocated?memory?from?log?pool
          *?Arguments??:?const?void?*p_vAddr?point?to?address?of?this?allocated?memory?by?this?pointer
          *?Returns??????:?void
          *?Notes????????:
          **********************************************************/

          static?void?UnlogDMem(const?void?*p_vAddr)
          {
          ????ASSERT(p_vAddr);
          ????DMEM_LOG????*p_stLog,?*p_stPrev;
          ????#if?OS_CRITICAL_METHOD?==?3
          ????OS_CPU_SR??cpu_sr;
          ????#endif

          ????/*?Search?the?log?*/
          ????OS_ENTER_CRITICAL();?/*Avoid?race?condition?*/
          ????p_stLog?=?p_stPrev?=?s_pstHeadLog;
          ????while?(p_stLog)
          ????{
          ????????if?(p_vAddr?==?p_stLog->p_vDMem)
          ????????{
          ?????????break;?/*?Have?found?*/
          ????????}??????????

          ????????p_stPrev?=?p_stLog;????????
          ????????p_stLog?=?p_stLog->p_stNext;????/*?Move?to?next?one?*/
          ????}
          ????
          ????if?(!p_stLog)
          ????{
          ????????OS_EXIT_CRITICAL();
          ????????PRINTF("Search?Log?failed.\r\n");?????????
          ????????return;
          ????}

          ????/*?Remove?from?used?pool?*/
          ????if?(p_stLog?==?s_pstHeadLog)
          ????{
          ?????s_pstHeadLog?=?s_pstHeadLog->p_stNext;
          ????}
          ????else
          ????{
          ?????p_stPrev->p_stNext?=?p_stLog->p_stNext;
          ????}
          ????--s_byNumUsedLog;
          ????OS_EXIT_CRITICAL();

          ????/*?Don't?need?to?protect?this?log?that?is?free?one?currently?*/
          ????p_stLog->p_vDMem?=?NULL;
          ????p_stLog->iSize?=?0;

          ????/*?Add?into?free?pool?*/
          ????OS_ENTER_CRITICAL();?/*?Avoid?race?condition?*/
          ????p_stLog->p_stNext?=?s_pstFreeLog;
          ????s_pstFreeLog?=?p_stLog;
          ????OS_EXIT_CRITICAL();

          ????return;
          }

          帶日志記錄功能的內(nèi)存分配MallocExt()和內(nèi)存釋放FreeExt()函數(shù):

          /*********************************************************????????????????????????????????????????????????????
          *??????????????????????Malloc?Extension
          *?Description?:?Malloc?a?block?of?memory?and?log?it?if?need
          *?Arguments?:?INT32S?iSize????size?of?desired?allocate?memory
          *?Returns:?void?*NULL=?failed,?otherwise=pointer?of?allocated?memory
          *?Notes????????:
          **********************************************************/

          void?*MallocExt(INT32S?iSize)
          {
          ????ASSERT(iSize?>?0);
          ????void?*p_vAddr;

          ????p_vAddr?=?malloc(iSize);
          ????if?(!p_vAddr)
          ????{
          ?????PRINTF("malloc?failed?at?%s?line?%d.\r\n",?__FILE__,?__LINE__);
          ????}
          ????else
          ????{
          ????????#if?(DMEM_DBG?&&?DBG_VER)
          ????????memset(p_vAddr,?0xA3,?iSize);?/*?Fill?gargage?for?debug?*/
          ????????LogDMem(p_vAddr,?iSize);????/*?Log?memory?for?debug?*/
          ????????#endif
          ????}

          ????return?p_vAddr;?????
          }

          /**********************************************************
          *??????????????????????Free?Extension
          *?Description?:?Free?a?block?of?memory?and?unlog?it?if?need
          *?Arguments??:?void?*?p_vMem?point?to?the?memory?by?this?pointer
          *?Returns??????:?void
          *?Notes????????:
          **********************************************************/

          void?FreeExt(void?*p_vMem)
          {
          ????ASSERT(p_vMem);

          ????free(p_vMem);??
          ????#if?(DMEM_DBG?&&?DBG_VER)
          ????UnlogDMem(p_vMem);????/*?Remove?memory?from?log?*/
          ????#endif
          ????return;
          }

          原文鏈接:https://blog.csdn.net/jiangjunjie_2005/article/details/26937879

          版權(quán)歸原作者所有,如有侵權(quán),請聯(lián)系刪除。

          ???????????????? ?END ?????????????????

          關(guān)注我的微信公眾號,回復(fù)“加群”按規(guī)則加入技術(shù)交流群。

          關(guān)注公眾號,回復(fù)“pdf”獲取程序員必讀經(jīng)典書單,一起編程一起進(jìn)階。



          點(diǎn)擊“閱讀原文”查看更多分享,歡迎點(diǎn)分享、收藏、點(diǎn)贊、在看。

          瀏覽 31
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評論
          圖片
          表情
          推薦
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  日韩一级免费播放 | 国产熟女乱伦 | 91一区二区三区 | 色妹子综合 | 日本免费成人撸一区二区三区 |