ImageVerifierCode 换一换
格式:DOCX , 页数:72 ,大小:46.13KB ,
资源ID:11148301      下载积分:3 金币
快捷下载
登录下载
邮箱/手机:
温馨提示:
快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。 如填写123,账号就是123,密码也是123。
特别说明:
请自助下载,系统不会自动发送文件的哦; 如果您已付费,想二次下载,请登录后访问:我的下载记录
支付方式: 支付宝    微信支付   
验证码:   换一换

加入VIP,免费下载
 

温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【https://www.bingdoc.com/d-11148301.html】到电脑端继续下载(重复下载不扣费)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: 微信登录   QQ登录  

下载须知

1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。
2: 试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。
3: 文件的所有权益归上传用户所有。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 本站仅提供交流平台,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

版权提示 | 免责声明

本文(低级错误案例集汇总.docx)为本站会员(b****3)主动上传,冰点文库仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知冰点文库(发送邮件至service@bingdoc.com或直接QQ联系客服),我们立即给予删除!

低级错误案例集汇总.docx

1、低级错误案例集汇总TOP1 资源泄漏 资源泄漏(包括内存泄漏)是代码Review中最常见的错误之一,申请的每个资源必须明确由谁负责释放,何时释放,在何处释放;在异常/错误/返回处理中,保持清醒的头脑,清理战场。此处的资源还包括信号量、定时器、文件句柄等系统资源。案例1.1【问题描述】 宏里面有return语句导致内存泄漏案例一。【问题分析】1) 错误代码:/*定义宏MODEL_ASSERT_RETFAIL*/#define MODEL_ASSERT_RETFAIL (X) if(X不合法) return; ./do somethingMDSTrafficMsg* pMsg = VOS_Allo

2、cMsg( PID_MD, usLength );if (NULL_PTR = = pMsg ) return ;MDSDataListenerMgr *pDataListener = MDSDataInitalListenerMgr();MODEL_ASSERT_RETFAIL(pDataListener);2)分析: 使用宏MODEL_ASSERT_RETFAIL检查pDataListener是否合法,如果不合法,则直接返回,一旦返回,将导致前面通过指针pMsg申请到的消息包资源泄漏。【纠正方法】在宏MODEL_ASSERT_RETFAIL分支判断return前加上VOS_FreeMsg(

3、PID_MD, pMsg ):该方法代码不够清晰,当用户看宏定义时,对VOS_FreeMsg(PID_MD, pMsg )不清楚还要跳回来看前面的代码。设定该宏有返回值(指针不为空返回VOS_True,否则为VOS_False),将宏的return语句写在宏使用后(判断指针pDataListener合法性),若宏返回VOS_False释放pMsg并返回主调函数:该方法在遇到只判断一个指针的合法性时,浪费代码行、降低代码飞检效率且可能存在宏描述歧义等问题,简单的判断建议不使用宏。【经验教训】在XX版本的一个新模块的开发中,在发布之前进行大话务量测试验证时,发现系统内存资源不足,当时发布在即,经过

4、协调多个技术专家封闭攻关,花了三天时间终于发现问题所在,人力成本高达3000元,对于内存使用,要确保释放闭环,所有异常退出点都需要释放内存。案例1.2【问题描述】 宏里面有return语句导致内存泄漏案例二。【问题分析】1) 错误代码:头文件中的宏定义如下:#define NODE_RETURN_ERROR (p) if (NULL = p) VOS_RECORD_ERROR(p); return NULL; 文件中有个函数有如下代码段:./do somethingpNode = (Node_Head_S *)malloc(sizeof(Node_Head_S);NODE_RETURN_ERR

5、OR (pNode);/第一次使用宏pBody = (Node_Body_S *)malloc(sizeof(Node_Body_S);NODE_RETURN_ERROR (pBody); /第二次使用宏./do something2)分析: 当通过指针pBody申请内存,然后通过宏NODE_RETURN_ERROR来判断是否申请成功,如果申请失败,则在宏NODE_RETURN_ERROR里面就直接返回了,这样导致通过指针pNode申请的内存泄漏了。【纠正方法】 不使用宏,或将宏中的return语句写到宏调用后。案例1.3【问题描述】 异常出口没有释放应该释放的内存案例一。【问题分析】1) 错

6、误代码:/ GetBuff函数的作用是申请动态内存pMsgDB_DEV = (PDBDevMsg)GetBuff( sizeof( DBDevMsg ), _LINE_);if ( NULL= = pMsgDB_DEV ) return;/ GetBuff函数的作用是申请动态内存pMsgDBApp_To_Logic = (LPDBSelfMsg)GetBuff( sizeof(DBSelfMsg), _LINE_ );if ( NULL = = pMsgDBApp_To_Logic ) return;2)分析: 在第2个return处,pMsgDB_DEV指向的内存丢失。【纠正方法】 在第2个

7、return处增加释放内存的操作。【经验教训】 函数中有动态申请内存,要在函数范围内检查所有return语句是否释放该return语句前所有动态申请的内存。案例1.4【问题描述】 申请过的内存的指针没有释放,又申请新的内存给它。【问题分析】1) 错误代码:/* 申请新的内存大小 */ pTmp = VOS_Malloc( pMacroEdit-ulMacroLen + 1 ) ; if( NULL = = pTmp ) return FAILURE ; VOS_MemSet( pTmp , 0 , pMacroEdit-ulMacroLen + 1 ); . /*又申请新的内存*/ pTmp

8、VOS_Malloc(sizeof(TTTT_RPC_MSG_S); if( NULL = = pTmp ) return FAILURE ; . VOS_Free(pTmp);2)分析: 第一次申请的内存没有释放就使用同一个指针又申请了内存。这样第一次申请的内存就永远没办法释放了,造成了内存泄漏。【纠正方法】 第2次申请内存前,先释放掉第1次申请的内存。同时我们应该注意到这个案例中对于申请的内存使用的指针变量是个临时变量,其命名没有十分明确的承载其所指向内存的含义,这样命名是不规范的,也许恰恰就是因为这点,才引发了后面继续直接使用.案例1.5【问题描述】 异常出口没有释放应该释放的资源。【问

9、题分析】1) 错误代码: intr_lock(); /*填充消息*/ ulResult = DEV_MA_FillMsg( pMsg ,ucPrimID, usBIndex, ucSerailID); if( ulResult != MSP_RETURN_NO_ERR ) VOS_FreeMsg( PID_DEV, pMsg ); return ulResult; intr_unlock(); 2)分析: return前没有调用intr_unlock()释放中断信号量。【纠正方法】 return前释放中断信号量。案例1.6【问题描述】 分支考虑不全,导致某些分支中内存泄漏。【问题分析】1) 错

10、误代码:/*创建消息,并放入消息队列中,假设处理成功*/ pMsg = CreateQueueMsg (j); mu = SortOperation(pMsg); if (mu = 0) ret = 0; else if (mu = 5) ret = SendMsgToMu(pMsg, mu-1); if (ret 5的分支,根本没有考虑,内存泄漏。【纠正方法】 增加mu5时对内存的释放处理。案例1.7【问题描述】 多个判断放在一起进行导致内存泄漏。【问题分析】1) 错误代码:char* pszInfoBuf1 = VOS_NULLPTR; char* pszInfoBuf2 = VOS_NU

11、LLPTR; pszInfoBuf1 = (char*)VOS_Malloc(MID_BVLAN, ulBuffLen); pszInfoBuf2 = (char*)VOS_Malloc(MID_BVLAN, ulBuffLen); if ( (pszInfoBuf1 = = NULL) | (pszInfoBuf2 = = NULL ) ) return VOS_ERR; 2)分析: 当pszInfoBuf1申请成功,但pszInfoBuf2申请失败时,if语句被执行,pszInfoBuf1指向的内存泄漏了。【纠正方法】 将两处申请内存后的有效性判断分开进行。案例1.8【问题描述】 内存重复

12、释放可能产生不可预知的后果。【问题分析】1) 错误代码:void NbvmConfirmBrdVer(NBOM_TRANS *pstTrans) if (NULL != pstTrans-pbDynMem) pstSelfBoardBootRomInfo = (NBVM_SELF_BOARD_BOOTROM_INFO*)(void*)pstTrans-pbDynMem; NBVM_MEM_FREE(pstSelfBoardBootRomInfo); NBVM_MEM_FREE(pstBrdAllSwInfo); NBVM_MEM_FREE(pstTrans-pbDynMem); NBVM_ME

13、M_FREE(pstTrans-pPrivatePtr);2)分析: 上述红色代码造成了pstTrans-pbDynMem所指向的内存重复释放。【纠正方法】 内存重复释放可能产生不可预知的后果:假如任务A申请了内存块M,使用后释放M;系统可能把空闲的M分配给了任务B,当任务A重复释放M后,把本来属于任务B的该内存块误释放;此时系统认为空闲的内存块M又可能分配给任务C,C随后对这个内存块的写操作对于任务B来说就是非法操作,可能导致任务B运行异常。案例1.9【问题描述】系统运行过程中,出现堆内存不足。【问题分析】1) 错误代码typedef struct tagWordStat char * ps

14、zWord; ULONG ulSum; float frate; struct tagWordStat * psnext;WORDSTAT_S, *PWORDSTAT_S;psWordName = (char *)malloc(ulCurWordLen + 1);if(NULL = psWordName) return VOS_ERR;/*获取字符串*/VOS_strncpy(psWordName, strName, ulCurWordLen);./*建立新节点*/pstWordStat = (PWORDSTAT_S)VOS_Malloc(sizeof(WORDSTAT_S);if ( NUL

15、L = pstWordStat ) VOS_Free(psWordName);return STAT_ERR; memset(pstWordStat, 0, sizeof(WORDSTAT_S); pstWordStat-pszWord = psWordName; psWordName = NULL; pstWordStat-ulSum = 1;pstWordStat-psnext = NULL;ulTotalWordNum +;./*释放节点*/VOS_Free(pstWordStat);.2)分析在释放节点时,只释放申请的部分内存。在这段代码中,字符串存放申请了一段内存,建立链表的节点又申

16、请了内存,最后只释放了链表节点内存,没有释放字符串存放时申请的内存。【纠正方法】 先释放结构体内指针成员申请的内存,再释放结构体指针指向的内存。释放结构体节点内存时,一定要搞清楚节点内部是否还有需要释放的内存,否则会导致这段内存永远得不到释放。TOP2 内存越界 所谓内存越界就是申请了内存,使用时超出了申请的范围。发生内存越界的情况,往往出错的地方不是真正内存越界的地方,带来的影响滞后,而且难以定位,需要程序员养成良好编程习惯,对指针,内存拷贝,字符串操作等注意前后空间的变化,可以做一些必要保护。案例2.1【问题描述】 数组下标访问越界。【问题分析】1) 错误代码:/* 初始化Q922的I帧链

17、路索引地址表 */ ulSize = sizeof(INDEX_Q922IFRAME_MAPPING_STRU *) * DCOM_MAXSERVICEQ922LINK;/ g_ppstQ922IFrameIndex申请的长度是DCOM_MAXSERVICEQ922LINK g_ppstQ922IFrameIndex = (INDEX_Q922IFRAME_MAPPING_STRU *)VOS_MemAlloc(VOS_PID_COMM, STATIC_DOPRA_MEM_PT, ulSize); .VOS_UINT32 Q922_AddLink(.) . if (usLinkNo DCOM_

18、MAXSERVICEQ922LINK) ulRet = VOS_ERRNO_Q922CFG_ADDLINK_LINKNO_INVALID; return ulRet; /* 初始化Q922的I帧映射表的信息 */ ulSize = sizeof(INDEX_Q922IFRAME_MAPPING_STRU); g_ppstQ922IFrameIndexusLinkNo = (INDEX_Q922IFRAME_MAPPING_STRU *)VOS_MemAlloc(VOS_PID_COMM, DYNAMIC_DOPRA_MEM_PT,ulSize); if (VOS_NULL_PTR = g_pp

19、stQ922IFrameIndexusLinkNo) . ulRet = VOS_ERRNO_Q922CFG_INIT_ALLOC_IFRAMEMAP_FAILED; return ulRet; .2)分析: 造成内存写越界,单板复位。【纠正方法】 内存申请最大长度是DCOM_MAXSERVICEQ922LINK,最多访问到g_ppstQ922IFrameIndexDCOM_MAXSERVICEQ922LINK-1,判断应改成if (usLinkNo = DCOM_MAXSERVICEQ922LINK)案例2.2【问题描述】 版本倒换,主控板一起来就出现指令异常,单板复位【问题分析】1) 错误

20、代码:CHAR sLogInfo1024; UCHAR szTmp10; /*只分配了10个字节*/ char* pTemp = sLogInfo; . while(*pTemp != -) szTmpi = *pTemp; /*没有找到-,继续进行,导致堆栈被写坏*/ pTemp+; i+; szTmpi = 0; 2)分析: 当数组下标i大于等于9时,不能再继续循环,否则越界访问。【纠正方法】 增加判断:i等于8时,跳出循环, 对于while或者for循环里操作数组下标要做下标的保护,“小心驶得万年船”案例2.3【问题描述】 入参检测失败后不退出函数,仍继续执行后面逻辑处理,导致后面使用数

21、组下标越界,在异常引用情况下导致死机。 【问题分析】1) 错误代码:void FAR Check_ImsDataTab_by_timer (CR ims_data_tab_cr) if (ims_data_tab_cr) = MAX_IMS_DATA_CR) A CCB_stop_timer_by_ftr(ims_data_tab_cr, EN_CCB_FTR_ID_RF, EN_RF_CHECK_SINGLE_IMSDATA_TIMER); 后面需要return,退出函数 if (MAX_SIPSL_CR = g_ims_data_tableims_data_tab_cr.sip_cr) B

22、 & (MAX_CCB(LOCAL_MODULE) = g_ims_data_tableims_data_tab_cr.ccb_cr) return; 2)分析: 当A处的ims_data_tab_cr 入参检查失败后不退出而继续进行下面的逻辑处理,导致B处引用ims_data_tab_cr作为数组下标越界【纠正方法】 在入参检测中失败应做退出函数处理,A处逻辑判断中增加return案例2.4【问题描述】 系统运行过程中突然复位。【问题分析】1) 错误代码: while ( _isspace( *szString ) ) /* 跳过所有空格字符 */ szString +; /szString

23、为函数的输入参数 if (0 = *szString ) return FAILURE ; /*=的左边变量赋值*/ szStr = VOS_Malloc( 20 ) ;/申请内存大小为给20 if( NULL = szStr ) return MACRO_MEM_SHORTAGE ; VOS_MemSet(szStr, 0, 20) ; VOS_StrCpy( szStr, szString ) ;2)分析: 这种内存写越界问题的表面现象是不确定的。该问题的原因就是没有检查szString字符串的长度,最后一代码中,字符串拷贝时发生写越界。【纠正方法】规避这种问题的办法是拷贝字符串是采用DO

24、PRA平台提供的安全拷贝函数CHAR * VOS_strncpy( CHAR *dst, const CHAR *src, ULONG n )。案例2.5【问题描述】 Sprintf使用不当导致内存访问越界【问题分析】1) 错误代码:char pszInfoBuf250; sprintf(pszInfoBuf,”* File:%s Line:%d *”,_FILE_,_LINE_);2)分析: “_FILE_”在预编译时,被编译时的目录名和源文件名代替,但目录和文件名的长度可变,很可能超出250个字节,导致内存越界【纠正方法】 将sprintf替换成安全函数snprintf,指定缓冲区大小IN

25、FOBUF_SIZE,确保内存不会越界 snprintf(pszInfoBuf,INFOBUF_SIZE -1,”* File:%s Line:%d *”,_FILE_,_LINE_); pszInfoBufINFOBUF_SIZE -1=0;【经验教训】 C语言提供的字符串库函数sprintf /vsprintf/strcpy/strcat/gets等非常危险,很容易导致内存越界,应该使用安全的字符串库函数snprintf/strncpy/strncat/fgets,指定操作的内存大小。对C语言,应该使用相应的类库如std:string,std:stringstream, boost:lex

26、ical_cast操作字符串,而不要直接调用C语言的字符串函数。案例2.6【问题描述】 Strcpy使用不当导致内存访问越界。【问题分析】1) 错误代码:char pszInfoBuf32; strcpy(pszInfoBuf,pMsg); 2)分析: 定义的pszInfoBuf共32字节,pMsg是从网络上接收的数据包,可能超出32个字节,导致内存越界【纠正方法】 将strcpy替换成安全函数strncpy ,指定缓冲区大小INFOBUF_SIZE,确保内存不会越界 strncpy (pszInfoBuf,pMsg, INFOBUF_SIZE - 1); pszInfoBufINFOBUF_

27、SIZE - 1=0; 案例2.7【问题描述】 字符串拼接,忘记后面的0.【问题分析】1) 错误代码:ulNewSize VOS_strlen(“rn”)+VOS_strlen(pRevData) + VOS_strlen(pszVlanInfo)+ VOS_strlen(pszQinQinfo);pszDisInfo = VOS_Malloc(MID_BVLAN, ulNewSize);./拷贝一些内容给pszDisInfoVOS_ strcat (pszDisInfo, pszQinQinfo); /字符串连接2)分析: 以ulNewSize为长度申请内存,但忘记字符串结尾必须有一个0,调

28、用strcat时拷贝了字符串本身和最后的0,导致内存越界【纠正方法】 计算ulNewSize时,增加1个字节,用于存放0.案例2.8【问题描述】 数组下标越界。【问题分析】1) 错误代码:/ pstPSCCfgInfo-strPara.ucNumOfCID超过了数组下标的最大值。for (ulCount = 0; ulCount strPara.ucNumOfCID; ulCount+) pPSCTable-strPara.stCidInfoulCount.bitCid = pstPSCCfgInfo-strPara.stCidInfoulCount.bitCid;2)分析: 外部配入的pst

29、PSCCfgInfo-strPara.ucNumOfCID值超过了定义的最大值SLP_MAX_PSC_CID_NUM。由于代码未加保护,导致数组下标越界。致BBI单板复位。【纠正方法】增加判断:if (SLP_MAX_PSC_CID_NUM strPara.ucNumOfCID)pstPSCCfgInfo-strPara.ucNumOfCID = SLP_MAX_PSC_CID_NUM;【经验教训】 对于外部输入的数组下标要作检查,避免内存越界案例2.9【问题描述】 整形转换成字符串时,没有注意到0结尾。 【问题分析】1) 错误代码:/使用itoa()将整型数转换为字符串时: char szTempShold10 ; itoa(ulProcFrecy,szTempShold,10);

copyright@ 2008-2023 冰点文库 网站版权所有

经营许可证编号:鄂ICP备19020893号-2