Klockwork告警常見錯誤

下面列舉的是Klockwork告警中常見的告警形式,這些狀況在編譯階段都不會報出來語法上的錯誤,而且在運行階段執行到的機率很小。可是在某些場景下一旦執行到了這些語句, 極可能引發進程的跑飛和掛起node

 
一、沒有對全部入參指針作有效性檢查
WORD32 Test(WORD32 *p,   WORD32 *q )
{
    WORD32 dwBindType = 0;
    if ((NULL == p) ||   (NULL == q) )
    {
        SF_ASSERT(0);
        return SFWD_ERROR;
    }
    return SFWD_OK;
}
 
編程規範要求,全部入參是指針,都必須進行判空操做;若是是入參是整型等,能夠根據須要決定是否對入參進行檢查;但參數不合法都要作異常處理;
 
二、函數中的異常處理缺乏返回值
WORD32 Test(WORD32 *p, WORD32 *q)
{
    WORD32 dwBindType = 0;
    if ((NULL == p) || (NULL == q))
    {
        SF_ASSERT(0);
          return SFWD_ERROR;        //致使與預期返回的結果不符
    }
    return SFWD_OK;
}
 
斷言須要作異常處理的,並非斷言就完事了,若是tr掉,繼續往下走,可能會出現跑飛或單板重啓等嚴重問題;
在release版本,斷言是被忽略的;debug版本,適當增長斷言,當出現異常時,容易定位問題。
 
三、函數在異常退出前務必要釋放先前申請的內存
SOCK_PKTINFO* Test(WORD32 dwReplyType)
{
    BYTE *pValidatePkt = NULL;
    SOCK_PKTINFO *pPktInfo = NULL;
 
    pValidatePkt = (BYTE *)   XOS_GetUB (VER_REPLY_PKTLEN);
    if (NULL == pValidatePkt)
    {
        ROSNG_TRACE_ERROR("Error: XOS_GetUB failed!\n");
        return NULL;
    }
    MEMSET(pValidatePkt, 0, VER_REPLY_PKTLEN);
 
    if (TOPO_REPLY_OK == dwReplyType)
    {
        MEMCPY(&pValidatePkt[4], "YES", 4);
    }
    else
    {
        SF_ASSERT(0);
        XOS_RetUB(pValidatePkt);
        return NULL;
    }
    return pPktInfo;
}
 
這段代碼其實有幾個問題:
1.沒有遵照誰申請誰釋放的原則,C語言很容易出現內存泄漏,但遵照規範,這種泄漏就會少不少;
  除了申請的內存須要緩存而不是在一個消息中釋放外(好比分片組包的狀況),報文處理中基本上能夠作到誰申請誰釋放;
2.在異常流程,沒有釋放內存,這個是很是容易犯的錯誤;
3.若是是臨時申請內存,應該使用PUB_GetLocalUB/PUB_RetLoacalUB這對接口;
 
 
四、函數內對空指針進行引用操做
VOID Test(SFWD_NBR_INFO *pNbrInfo)
{
    WORD32 * pIndex   = NULL;
 
    if(NULL == pNbrInfo)
    {
        ROSNG_TRACE_ERROR("Error: Para is NULL!\n");
        SF_ASSERT(0);
        return;
    }
 
    if(0 == pNbrInfo->wActiveNbrNum)
    {
          pIndex   = sfwd_node_new(sizeof(WORD32));
        if(NULL == pIndex)
        {
            ROSNG_TRACE_ERROR("Error: sfwd_node_new return NULL!\n");
            return;
        }
        *   pIndex   = pVifInfo->dwIndex;
       
    }
    XOS_RawPrint("gIndex = %d, pNbrInfo->dwNbrStatus = %d\n", *   pIndex , pNbrInfo->dwNbrStatus);
      //這裏若是沒有執行上面if語句內的代碼,就會致使對空指針進行操做;
    return;
}
 
無論是打印仍是語句,只有是訪問指針指向的內容,先想一想這個指針有沒有爲空或非法地址的狀況;
 
五、函數中數組操做的越界訪問
WORD32 Test(SFWD_TOPO_PKT_CAP_IF_INFO_T *pIfInfo, WORD32 gIndex)
{
    WORD32 dwSubslot = 0;
    WORD32 dwSubindex = 0;
    WORD16 if_type = 0;
 
    if (NULL == pIfInfo)
    {
        ROSNG_TRACE_ERROR("sfwd_topo_pkt_cap_get_ifinfo: inParam is NULL!\n");
        SF_ASSERT(0);
        return FALSE;
    }
 
    if ((gIndex <= 0))
    {
        ROSNG_TRACE_ERROR("sfwd_topo_pkt_cap_get_ifinfo: Para error!\n");
        SF_ASSERT(0);
        return FALSE;
    }
 
      dwSubslot   = gIndex / MAX_IF_NUMBER_PERCARD;
      dwSubindex   = gIndex % MAX_IF_NUMBER_PERCARD;
    if((dwSubslot >= MAX_SUBCARD_NUMBER) || (dwSubindex > MAX_IF_NUMBER_PERCARD))  
    {
        ROSNG_TRACE_WARNING("sfwd_topo_pkt_cap_get_ifinfo: invalid subslot or subindex.\n");
        SF_ASSERT(0);
        return FALSE;
    }
      if_type = gInterface[dwSubslot][dwSubindex].wType;
      //在對gInterface數組進行訪問時,若是dwSubslot、dwSubindex的下標值超出了該數組聲明的大小可能產生越界。因此,須要根據代碼的上下文來對數組的下標作有效性檢查(並非全部的數組訪問都檢查,有些是不必的)
 
    return TRUE;
}
 
#define SFWD_SUBCARD_NO_CHECK(A, B)    ((A >= MAX_SUBCARD_NUMBER) || (B > MAX_IF_NUMBER_PERCARD))
 
數組越界也是常常犯的錯誤,對數組的訪問,加一下檢查;考慮到會頻繁出現數組下標的檢查,能夠寫一個相似上面的宏;
相關文章
相關標籤/搜索