代码审查九句真言.docx

上传人:b****5 文档编号:5386076 上传时间:2022-12-15 格式:DOCX 页数:19 大小:24.24KB
下载 相关 举报
代码审查九句真言.docx_第1页
第1页 / 共19页
代码审查九句真言.docx_第2页
第2页 / 共19页
代码审查九句真言.docx_第3页
第3页 / 共19页
代码审查九句真言.docx_第4页
第4页 / 共19页
代码审查九句真言.docx_第5页
第5页 / 共19页
点击查看更多>>
下载资源
资源描述

代码审查九句真言.docx

《代码审查九句真言.docx》由会员分享,可在线阅读,更多相关《代码审查九句真言.docx(19页珍藏版)》请在冰豆网上搜索。

代码审查九句真言.docx

代码审查九句真言

看见了If,就想Else。

看见malloc,就去找Free。

函数调用要小心,需要看看返回值。

看到for循环,就找边界值。

看见return要注意,要去前面找资源。

看见数组把神提,问题往往在下标。

不要小看字符串,长度是个大问题。

得到函数不要急,看看变量初始化,各种路径要小心。

赋值函数最危险,变量没有初始化。

九句句真言不孤立,相互结合显神威。

 

真言详解

1.看见If,就想Else。

看到if语句,就要想到else语句。

如果没有else语句,就要分析是不需要,还是异常情况没有处理,如果是异常情况没有处理,可以提单。

2.看见malloc,就去找Free。

看到malloc语句分配了内存,立即停下正常走读,看malloc代码之后,是否在所有程序的返回分支中都有释放语句。

典型案例:

U32DEV_IfSetSectionEnable(DEV_IF_T*pIfIns)

{

CHAR*pSectionName=NULL;

ULONGulMsg[4];

/*向配置文件发送消息DEV_IF_READ_SECTION,进行配置下载*/

pSectionName=VOS_Malloc(MOD_DEV,MAX_INTERFACE_NAME_LEN+1);

if(pSectionName!

=NULL)

{

VOS_strcpy(pSectionName,pIfIns->ifName);

ulMsg[0]=MID_DEV;

ulMsg[1]=MID_CFM;

ulMsg[2]=DEV_CFM_ENABLE_SECTION;

ulMsg[3]=(ULONG)pSectionName;

VOS_Que_Write(ulVRPQID_CFM,ulMsg,VOS_NO_WAIT,0);

returnSUCCESS;

}

returnDEV_ERR_NOMEMORY;

}

该函数有了VOS_Malloc,但没有看到free。

于是在下面的代码中寻找,发现VOS_Que_Write中自动实现free功能。

代码看似没有问题,但我们发现VOS_Que_Write的返回值没有判断,如果VOS_Que_Write返回失败,free语句就没有被执行到。

这样可以确认该函数存在内存泄露隐患。

该代码最终修改:

U32DEV_IfSetSectionEnable(DEV_IF_T*pIfIns)

{

CHAR*pSectionName=NULL;

ULONGulMsg[4];

ULONGrc;

/*向配置文件发送消息DEV_IF_READ_SECTION,进行配置下载*/

if(pIfIns==NULL||(VOS_strlen(pIfIns->ifName)>(MAX_INTERFACE_NAME_LEN+1)))

{

returnDEV_ERR_GEN;

}

pSectionName=VOS_Malloc(MOD_DEV,MAX_INTERFACE_NAME_LEN+1);

if(pSectionName!

=NULL)

{

VOS_strcpy(pSectionName,pIfIns->ifName);

ulMsg[0]=MID_DEV;

ulMsg[1]=MID_CFM;

ulMsg[2]=DEV_CFM_ENABLE_SECTION;

ulMsg[3]=(ULONG)pSectionName;

rc=VOS_Que_Write(ulVRPQID_CFM,ulMsg,VOS_NO_WAIT,0);

if(rc!

=SUCCESS)

{

rc=VOS_Free(pSectionName);

VOS_DBGASSERT(rc==VOS_OK);

returnDEV_ERR_GEN;

}

returnSUCCESS;

}

returnDEV_ERR_NOMEMORY;

}

 

3.函数调用要小心,需要看看返回值。

看到函数调用,要养成习惯,进入函数内部瞄一眼。

看看函数的正常值和异常值都是什么。

看看返回值需不需要判断。

看看有没有参数理解不一致的地方。

例如:

if(VOS_strnicmp(szFullName,DEV_ATM_NAME,DEV_ATM_NAMELEN)==0)

{

ulIfType=DEV_GetIfTypeFromIfName(szFullName);

if(ulIfType==-1)

{

EXEC_OutString(ulExecID,"\r\nUnknowninterfacetype");

returnVOS_ERR;

}

/*得到端口的索引*/

ulRet=DEV_GetIfIndexFromIfName(szFullName,&ulIfIndex);

if(SUCCESS!

=ulRet)

{

EXEC_OutString(ulExecID,"\r\nUnknowninterfacenumber");

returnVOS_ERR;

}

/*判断端口是否已经存在*/

pIfIns=DEV_GetIfFromIndex(ulIfIndex);

if(NULL==pIfIns)

{

rc=DEV_Cnsl_CreateIf(ulExecID,ulIfType,ulIfIndex,ulSubType);

if(SUCCESS!

=rc)

{

returnSUCCESS;

}

pIfIns=DEV_GetIfFromIndex(ulIfIndex);

if(NULL==pIfIns)

{

COUT_OUTPUT_DIAG(MOD_DEV,COUT_LEVEL_WARNING,"pIfIns=NULLisinvalid%s.%d"

__FILE__,__LINE__);

returnDEV_ERR_GEN;

}

函数使用-1作为非法值,而在DEV_GetIfTypeFromIfName函数中:

U32DEV_GetIfTypeFromIfName(CHAR*ifName)

{

CHARszIfType[20];//接口的类型字符串

U32ulIfType;

U32strLen;

U32i;

if(NULL==ifName)

{

COUT_OUTPUT_DIAG(MOD_DEV,COUT_LEVEL_WARNING,"ifName=NULLinGetIfTypeFromIfName%s.%d",__FILE__,__LINE__);

returnDEV_ERR_VALUE;

}

strLen=VOS_strlen(ifName);

if(0==strLen)

{

/*字符串为空,返回错误*/

COUT_OUTPUT_DIAG(MOD_DEV,COUT_LEVEL_WARNING,"strlen=0%s.%d",__FILE__,__LINE__);

returnDEV_ERR_VALUE;

}

VOS_Mem_Set(szIfType,0,sizeof(szIfType));

/*---------------------------------------------------------*/

/*从字符串的尾部向前查找,直到找到第一个不是数字的字符*/

/*---------------------------------------------------------*/

for(i=strLen-1;i>=0;i--)

{

/*字符不等于'.','/'或数字字符时循环结束*/

if(ifName[i]!

='.'&&ifName[i]!

='/'

&&(ifName[i]<'0'||ifName[i]>'9'))

break;

}

VOS_strncpy(szIfType,ifName,i+1);

ulIfType=DEV_IfStringToType(szIfType);

returnulIfType;

}

函数的一个错误返回值是DEV_ERR_VALUE,很显然,两边参数理解不一致。

4.看到for循环,就找边界值。

看到for循环,就要看看边界值是否合理。

如果循环变量是数组的下标,更加需要注意。

例如:

U8*DEV_IfTypeToString(U32ulIfType)

{

U32i;

//changetousertype

ulIfType=DEV_IfUserType(ulIfType);

for(i=0;ulIfType!

=-1&&i

&&UserIfTypes[i].ulIfType!

=-1;i++)

{

if(UserIfTypes[i].ulIfType==ulIfType)

returnUserIfTypes[i].pIfTypeString;

}

return"unknown-interface";

}

函数中:

#defineDEV_USERIFTYPE_NUM9//numberofUserIfTypes,NOTDEV_IFTYPE_MAX_NUM!

!

!

而数组:

staticIfTypeList_SUserIfTypes[]=

{

{DEV_IFTYPE_ATM,"Atm","ATMinterface",3,0,DEV_AATMIF_LOGIF_MAX_NUM},

#ifndefISN_MODIFIED

//Modifiedby:

liyanmin

//Data:

2001/1/3

//Description:

8850设备目前只管理ATM物理端口和ATM子接口?

{DEV_ATM_TYPE_VPT,CLI_CMD_TEMPLET_IF_ATMVPT,"ATMVPtunnel",4,DEV_AATMIF_LOGIF_MAX_NUM,0},

{DEV_ATM_TYPE_VPRT,CLI_CMD_TEMPLET_IF_ATMVPRT,"ATMVPringtunnel",4,DEV_AATMIF_LOGIF_MAX_NUM,0},

#endif//endISN_MODIFIED

{DEV_ATM_TYPE_ATMSUB,"atm-sub","ATMsub-interfaceforIP",4,DEV_AATMIF_LOGIF_MAX_NUM,0},

#ifndefISN_MODIFIED

{DEV_IFTYPE_SONET,CLI_CMD_TEMPLET_IF_POS,"IPPOSinterface",3,0,0},

{DEV_IFTYPE_FASTETHERNET,CLI_CMD_TEMPLET_IF_FASTETHERNET,"IP10M/100Methernetinterface",3,0,DEV_AFE_VLAN_MAX_NUM},

{DEV_IFTYPE_GIGABITETHERNET,CLI_CMD_TEMPLET_IF_GIGAETHERNET,"IP1000Methernetinterface",3,0,DEV_AGE_VLAN_MAX_NUM},

{DEV_IFTYPE_VT,"virtual-template","IPPPPvirtualtemplete",1,1,0},

{DEV_IFTYPE_VE,CLI_CMD_TEMPLET_VIRTUAL_ETHERNET,"IPvirtualethernetforPPPOE",3,1,0},

//no{DEV_IFTYPE_L3IPVLAN,"vlan","IPvirtualLAN",1,0},

#endif//endISN_MODIFIED

{-1,"","",0,0},

};

而数组定义中,去掉被注释掉的部分,数组长度只有3。

数组将严重越界。

5.看见return要注意,要去前面找资源。

看见return语句,尤其是函数中间的异常返回语句。

看到这种语句,就需要折回头去看看前面有没有分配资源。

前面分配的任何资源(包括内存,端口,等等),在异常返回处需要一并释放。

例如:

在PVC_vl.c中的ULONGAllocateVl(void*pMsgEnv)函数中,

if(pValue->rxTDscrIndex)

{

rc=TD_IncreaseTDRefer(pValue->rxTDscrIndex);

if(rc)

{

#ifPVC_APS_ENABLE==YES

APS_DecrProtectConf(void);

#endif

returnPVC_TRAFF_ERROR;

}

newVlEntry.rxIndex=pValue->rxTDscrIndex;

}

if(pValue->txTDscrIndex)

{

rc=TD_IncreaseTDRefer(pValue->txTDscrIndex);

if(rc)

{

TD_DecreaseTDRefer(pValue->rxTDscrIndex);

#ifPVC_APS_ENABLE==YES

APS_DecrProtectConf(void);

#endif

returnPVC_TRAFF_ERROR;

}

newVlEntry.txIndex=pValue->txTDscrIndex;

}

 

if(newVlEntry.txIndex&&newVlEntry.rxIndex)

newVlEntry.direction=BI_DIRECTIONAL;

elseif(newVlEntry.rxIndex)

newVlEntry.direction=RECEIVE;

else

newVlEntry.direction=TRANSMIT;

/*checkvirtuallinkselfconsistency*/

rc=CheckVlSelfConsistency(&newVlEntry);

if(rc)

{

#ifPVC_APS_ENABLE==YES

APS_DecrProtectConf(void);

#endif

TD_DecreaseTDRefer(newVlEntry.rxIndex);

TD_DecreaseTDRefer(newVlEntry.txIndex);

returnrc;

}

/*createvirtuallink*/

newVlEntry.port=port;

newVlEntry.vpi=vpi;

newVlEntry.vci=vci;

newVlEntry.atmOperStatus=PVC_DOWN;

newVlEntry.atmAlarmStatus=PVC_NOALARM;

newVlEntry.oamSegEndPoint=PVC_NOT_ENDPT;

newVlEntry.oamEndEndPoint=PVC_NOT_ENDPT;

newVlEntry.status=ROW_STATUS_UNKNOWN;

newVlEntry.vlFlag=PVC_NONRING;

VOS_Tm_Get(&newVlEntry.date,&newVlEntry.time,&newVlEntry.msec);

/*checkupcflagvalue*/

if(PVC_CHECK_UPCNPCFLAG(pValue->upc))

returnPVC_BAD_VALUE;

/*p2mpleaf禁止设置UPC*/

if(newVlEntry.atmCastType==P2MPLEAF&&pValue->upc==ENABLE)

returnPVC_STATE_ERROR;

else

newVlEntry.atmConnUpcNpcEnb=pValue->upc;

红色代码处分配了资源,而在兰色代码处异常返回时没有被释放。

6.看见数组把神提,问题往往在下标。

函数中一旦出现数组,就要提起精神。

数组越界可是个致命问题。

例如:

ULONGDEV_ExecNetSwitchShow(ULONGulUserID)

{

NM_VALUE_TsValue;

U32frmIndex;

U32slotIndex;

U32netIndex1,netIndex2;

U32netstatus1=DEV_OBJ_STATUS_INACTIVE;

U32netstatus2=DEV_OBJ_STATUS_INACTIVE;

DEV_FRAME_T*pFrame;

DEV_SLOT_T*pSlotIns;

DEV_SLOT_T*pNetIns1;

DEV_SLOT_T*pNetIns2;

U32rc;

U32i,j;//LoopVariable

U8pOutputStr[80];//outputinfobuffer

U32ulNet[DEV_SLOT_ATMUNIT_MAX_NUM];

U8*pOutputStatus;

U8*pOutputType;

U8*pOutputApcNet[DEV_ASLT_SUB_MAX_NUM-1];

U8xidx,yidx,tmpPort;

U32ulNetVer;

U32ulSeq;

U32ulLen;

void*pData;//pointertomsgreceived

U8szBuf[256];

DEV_NET_SWPTMAP_TsNetSwptMap;

//checknetboard

netIndex1=DEV_CONV_SLT2SLTINDEX(NET_CARD1);

netIndex2=DEV_CONV_SLT2SLTINDEX(NET_CARD2);

pNetIns1=DEV_GetSlotFromIndex(netIndex1);

pNetIns2=DEV_GetSlotFromIndex(netIndex2);

if(pNetIns1==NULL&&pNetIns2==NULL)

{

EXEC_OutString(ulUserID,"\r\nnetboardnotfound");

returnSUCCESS;

}

if(pNetIns1!

=NULL)

{

rc=DEV_SltGetSlotStatus(netIndex1,&sValue);

if(rc)

{

//erroroutput

returnDEV_ERR_GEN;

}

if(sValue.v_num!

=DEV_OBJ_STATUS_INACTIVE)

netstatus1=DEV_OBJ_STATUS_ACTIVE;

}

if(pNetIns2!

=NULL)

{

rc=DEV_SltGetSlotStatus(netIndex2,&sValue);

if(rc)

{

//erroroutput

returnDEV_ERR_GEN;

}

if(sValue.v_num!

=DEV_OBJ_STATUS_INACTIVE)

netstatus2=DEV_OBJ_STATUS_ACTIVE;

}

if(netstatus1==DEV_OBJ_STATUS_INACTIVE&&netstatus2==DEV_OBJ_STATUS_INACTIVE)

{

EXEC_OutString(ulUserID,"\r\nallthenetboardareinacitve");

returnSUCCESS;

}

//defaultframenumberis0

frmIndex=DEV_CONV_FRM2FRMINDEX(DEV_DEFAULT_FRAME);

pFrame=DEV_GetFrmFromIndex(frmIndex);

if(pFrame==NULL)//theframedoesn'texist!

{

COUT_OUTPUT_DIAG(MOD_DEV,COUT_LEVEL_WARNING,"pFrame=NULL%s.%d"

__FILE__,__LINE__);

returnDEV_ERR_GEN;

}

EXEC_OutString(ulUserID,"\r\nSlotTypeStateApc0Apc1Apc2Apc3");

EXEC_OutString(ulUserID,"\r\n-----------------------------");

for(i=0;i

{

slotIndex=pFrame->slotArrayIndex[i];

if(slotIndex==DEV_OBJINDEX_NOEXIST)

{

continue;

}

//getslotstatus

rc=DEV_SltGetSlotStatus(slotIndex,&sValue);

if(rc)

{

//erroroutput

returnDEV_ERR_GEN;

}

pOutputStatus=slotstatus[sValue.v_num];

if(sValue.v_num!

=DEV_OBJ_STAT

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 高等教育 > 其它

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1