尽管在开发过程中坚守原则和谨慎编程,甚至严格测试。然而内存泄露的错误还是难以杜绝,如何让系统自动查出内存泄露的错误呢?
一种比较好的方法是建立日志块,即每次分配内存时记录该内存块的指针和大小,释放时再去除该日志块,如果有内存泄露就会有对应的日志块记录这些内存没有释放,这样就可以提醒程序员进行查错。
有了上述日志块操作函数,再来实现动态内存分配与释放函数就很容易了。
(资料图片)
只有当处于 DEBUG 版本和打开内存调试 DMEM_DBG 时才进行日志登录,否则 MallocExt() 和 FreeExt() 函数与 malloc() 和 free() 是等价的,这样保证了系统处于发布版本时的性能(代码已经过严格测试,但这不是盈利的商业代码,即没有版权。但如果因代码错误带来的任何损失作者具有免责权利)。
首先定义日志块结构体:
/*Logofdynamicmemoryusage*/typedefstruct_dmem_log{struct_dmem_log*p_stNext;/*Pointtonextlog*/constvoid*p_vDMem;/*Pointtoallocatedmemorybythispointer*/INT32SiSize;/*Sizeoftheallocatedmemory*/}DMEM_LOG;
然后为该结构体开辟内存:
staticDMEM_LOG*s_pstFreeLog;/*Pointtofreelogpoolbythispointer*/staticINT8Us_byNumUsedLog;staticDMEM_LOG*s_pstHeadLog;/*Pointtousedlogchainbythispointer*//*Poolofdynamicmemorylog*/#defineNUM_DMEM_LOG20staticDMEM_LOGs_astDMemLog[NUM_DMEM_LOG];
下面是内存日志块的操作函数:初始化、插入日志和移除日志:
/***********************************************************InitializeDMemLog*Description:Initializelogofdynamicmemory*Arguments:void*Returns:void*Notes:**********************************************************/staticvoidInitDMemLog(void){INT16SnCnt;/*Initializepooloflog*/for(nCnt=0;nCnt0);DMEM_LOG*p_stLog;#ifOS_CRITICAL_METHOD==3OS_CPU_SRcpu_sr;#endif/*Getalogfromfreepool*/OS_ENTER_CRITICAL();/*Avoidraceconditionons_pstFreeLog*/if(!s_pstFreeLog){OS_EXIT_CRITICAL();PRINTF("AllocateDMemLogfailed.\r\n");return;}p_stLog=s_pstFreeLog;s_pstFreeLog=s_pstFreeLog->p_stNext;OS_EXIT_CRITICAL();/*Don"tneedtoprotectthislogthatisfreeonecurrently*/p_stLog->p_vDMem=p_vAddr;p_stLog->iSize=iSize;/*Putthislogintousedchain*/OS_ENTER_CRITICAL();/*Avoidracecondition*/p_stLog->p_stNext=s_pstHeadLog;s_pstHeadLog=p_stLog;++s_byNumUsedLog;OS_EXIT_CRITICAL();return;}/***********************************************************UnlogDMem*Description:Removeanallocatedmemoryfromlogpool*Arguments:constvoid*p_vAddrpointtoaddressofthisallocatedmemorybythispointer*Returns:void*Notes:**********************************************************/staticvoidUnlogDMem(constvoid*p_vAddr){ASSERT(p_vAddr);DMEM_LOG*p_stLog,*p_stPrev;#ifOS_CRITICAL_METHOD==3OS_CPU_SRcpu_sr;#endif/*Searchthelog*/OS_ENTER_CRITICAL();/*Avoidracecondition*/p_stLog=p_stPrev=s_pstHeadLog;while(p_stLog){if(p_vAddr==p_stLog->p_vDMem){break;/*Havefound*/}p_stPrev=p_stLog;p_stLog=p_stLog->p_stNext;/*Movetonextone*/}if(!p_stLog){OS_EXIT_CRITICAL();PRINTF("SearchLogfailed.\r\n");return;}/*Removefromusedpool*/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"tneedtoprotectthislogthatisfreeonecurrently*/p_stLog->p_vDMem=NULL;p_stLog->iSize=0;/*Addintofreepool*/OS_ENTER_CRITICAL();/*Avoidracecondition*/p_stLog->p_stNext=s_pstFreeLog;s_pstFreeLog=p_stLog;OS_EXIT_CRITICAL();return;}
带日志记录功能的内存分配 MallocExt() 和内存释放 FreeExt() 函数:
/**********************************************************MallocExtension*Description:Mallocablockofmemoryandlogitifneed*Arguments:INT32SiSizesizeofdesiredallocatememory*Returns:void*NULL=failed,otherwise=pointerofallocatedmemory*Notes:**********************************************************/void*MallocExt(INT32SiSize){ASSERT(iSize>0);void*p_vAddr;p_vAddr=malloc(iSize);if(!p_vAddr){PRINTF("mallocfailedat%sline%d.\r\n",__FILE__,__LINE__);}else{#if(DMEM_DBG&&DBG_VER)memset(p_vAddr,0xA3,iSize);/*Fillgargagefordebug*/LogDMem(p_vAddr,iSize);/*Logmemoryfordebug*/#endif}returnp_vAddr;}/***********************************************************FreeExtension*Description:Freeablockofmemoryandunlogitifneed*Arguments:void*p_vMempointtothememorybythispointer*Returns:void*Notes:**********************************************************/voidFreeExt(void*p_vMem){ASSERT(p_vMem);free(p_vMem);#if(DMEM_DBG&&DBG_VER)UnlogDMem(p_vMem);/*Removememoryfromlog*/#endifreturn;}
原文:https://blog.csdn.net/jiangjunjie_2005/article/details/26937879
关注我【一起学嵌入式】,一起学习,一起成长。
觉得文章不错,点击“分享”、“赞”、“在看” 呗!