代码审查九句真言
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
看见了If,就想Else。
看见malloc,就去找Free。
函数调用要小心,需要看看返回值。
看到for循环,就找边界值。
看见return要注意,要去前面找资源。
看见数组把神提,问题往往在下标。
不要小看字符串,长度是个大问题。
得到函数不要急,看看变量初始化,各种路径要小心。
赋值函数最危险,变量没有初始化。
九句句真言不孤立,相互结合显神威。
真言详解
1.看见If,就想Else。
看到if语句,就要想到else语句。如果没有else语句,就要分析是不需要,还是异常情况没有处理,如果是异常情况没有处理,可以提单。
2.看见malloc,就去找Free。
看到malloc语句分配了内存,立即停下正常走读,看malloc代码之后,是否在所有程序的返回分支中都有释放语句。
典型案例:
U32 DEV_IfSetSectionEnable(DEV_IF_T *pIfIns)
{
CHAR * pSectionName = NULL;
ULONG ulMsg[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);
return SUCCESS;
}
return DEV_ERR_NOMEMORY;
}
该函数有了VOS_Malloc,但没有看到free。于是在下面的代码中寻找,发现VOS_Que_Write中自动实现free功能。代码看似没有问题,但我们发现VOS_Que_Write的返回值没有判断,如果VOS_Que_Write返回失败,free语句就没有被执行到。这样可以确认该函数存在内存泄露隐患。该代码最终修改:U32 DEV_IfSetSectionEnable(DEV_IF_T *pIfIns)
{
CHAR * pSectionName = NULL;
ULONG ulMsg[4];
ULONG rc;
/* 向配置文件发送消息DEV_IF_READ_SECTION, 进行配置下载*/
if(pIfIns == NULL || (VOS_strlen( pIfIns->ifName) > (MAX_INTERFACE_NAME_LEN+1)))
{
return DEV_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);
return DEV_ERR_GEN;
}
return SUCCESS;
}
return DEV_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\nUnknown interface type" );
return VOS_ERR;
}
/*得到端口的索引*/
ulRet = DEV_GetIfIndexFromIfName( szFullName, &ulIfIndex);
if (SUCCESS != ulRet)
{
EXEC_OutString( ulExecID, "\r\nUnknown interface number" );
return VOS_ERR;
}
/*判断端口是否已经存在*/
pIfIns = DEV_GetIfFromIndex(ulIfIndex);
if(NULL == pIfIns)
{
rc = DEV_Cnsl_CreateIf(ulExecID, ulIfType, ulIfIndex, ulSubType);
if(SUCCESS != rc)
{
return SUCCESS;
}