下面列举的是Klockwork告警中常见的告警形式,这些情况在编译阶段都不会报出来语法上的错误,并且在运行阶段执行到的概率很小。但是在某些场景下一旦执行到了这些语句, 很可能引起进程的跑飞和挂起。

 
1、没有对所有入参指针做有效性检查
WORD32 Test(WORD32 *p, WORD32 *q)
{
    WORD32 dwBindType = 0;
    if ((NULL == p) || (NULL == q))
    {
        SF_ASSERT(0);
        return SFWD_ERROR;
    }
    return SFWD_OK;
}
 
编程规范要求,所有入参是指针,都必须进行判空操作;如果是入参是整型等,可以根据需要决定是否对入参进行检查;但参数不合法都要做异常处理;
 
2、函数中的异常处理缺少返回值
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版本,适当增加断言,当出现异常时,容易定位问题。
 
3、函数在异常退出前务必要释放先前申请的内存
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这对接口;
 
 
4、函数内对空指针进行引用操作
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;
}
 
不管是打印还是语句,只有是访问指针指向的内容,先想想这个指针有没有为空或非法地址的情况;
 
5、函数中数组操作的越界访问
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))
 
数组越界也是经常犯的错误,对数组的访问,加一下检查;考虑到会频繁出现数组下标的检查,可以写一个类似上面的宏;

Klockwork告警常见错误的更多相关文章

  1. 初识JAVA(二)(送给Java和安卓初学者)----常见错误

    博主接着上篇的来讲哦,以后的更新中,博主会出一些练习题,有兴趣的可以做做然后吧代码粘贴到下面,大家可以一起研究学习,一起进步,本篇文章主要讲的是: 一.常见错误 二.连接上篇一起的训练 无论是什么方向 ...

  2. ubuntu 常见错误--Could not get lock /var/lib/dpkg/lock

    ubuntu 常见错误--Could not get lock /var/lib/dpkg/lock 通过终端安装程序sudo apt-get install xxx时出错:E: Could not ...

  3. coreseek常见错误原因及解决方法

    coreseek常见错误原因及解决方法 Coreseek 中文全文检索引擎 Coreseek 是一款中文全文检索/搜索软件,以GPLv2许可协议开源发布,基于Sphinx研发并独立发布,专攻中文搜索和 ...

  4. Android Fragment使用(二) 嵌套Fragments (Nested Fragments) 的使用及常见错误

    嵌套Fragment的使用及常见错误 嵌套Fragments (Nested Fragments), 是在Fragment内部又添加Fragment. 使用时, 主要要依靠宿主Fragment的 ge ...

  5. C语言初学者代码中的常见错误与瑕疵(23)

    见:C语言初学者代码中的常见错误与瑕疵(23)

  6. struts2.5框架使用通配符指定方法常见错误

    struts2.5框架使用通配符指定方法(常见错误) 在学习struts框架时经常会使用到通配符调用方法,如下: <package name="shop" namespace ...

  7. .Net常见错误

    常见错误 #1: 把引用当做值来用,或者反过来 C++ 和其他很多语言的程序员,习惯了给变量赋值的时候,要么赋单纯的值,要么是现有对象的引用.然而,在C# 中,是值还是引用,是由写这个对象的程序员决定 ...

  8. WCF项目中出现常见错误的解决方法:基础连接已经关闭: 连接被意外关闭

    在我们开发WCF项目的时候,常常会碰到一些莫名其妙的错误,有时候如果根据它的错误提示信息,一般很难定位到具体的问题所在,而由于WCF服务的特殊性,调试起来也不是那么方便,因此往往会花费不少时间来进行跟 ...

  9. Python程序的常见错误(收集篇)

    关于Python Python是一门解释性的,面向对象的,并具有动态语义的高级编程语言.它高级的内置数据结构,结合其动态类型和动态绑定的特性,使得它在快速应用程序开发(Rapid Applicatio ...

随机推荐

  1. WinForms C#:html编辑器工程源码,含直接写WebBrowser的文件流、IPersistStreamInit接口的声明和一些相关的小方法

    原文:WinForms C#:html编辑器工程源码,含直接写WebBrowser的文件流.IPersistStreamInit接口的声明和一些相关的小方法 首先多谢朋友们的捧场: 今天给大家带来一个 ...

  2. 基于OCR的SeeTest框架可行性分析总结

    总的来说相比其他几个免费框架,SeeTest功能更全面和易用,但收费有点昂贵:License 3500/年:多平台和多语言(基于OCR)还需要额外购买,分别是500/Year和1750$/.详情请查看 ...

  3. 设计模式---订阅发布模式(Subscribe/Publish)

    设计模式---订阅发布模式(Subscribe/Publish) 订阅发布模式定义了一种一对多的依赖关系,让多个订阅者对象同时监听某一个主题对象.这个主题对象在自身状态变化时,会通知所有订阅者对象,使 ...

  4. Docker运行 Mono

    Docker运行 Mono Docker 是最近相当热门的一个名词,它是一个基于 Linux Container 的轻量化的虚拟技术,而微软也相当积极与 Docker 合作,在 Azure 上支持这个 ...

  5. 一个可以直接使用的MsgBox基于form居中API

    可直接复制DialogBox项目(文件夹)到需要的项目中然后直接引用和using CodeProject.Dialog 已修正原作者代码错误的地方,可直接使用,VS2010测试成功 具体可以参考案例T ...

  6. 自己编译的openwrt在开机时一直打印jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found...的错误提示

    具体的输入信息是这样的. uboot> http Link down: eth0 Ethernet mode (duplex/speed): / Mbps HTTP server is star ...

  7. 【UNIX网络编程(一)】套接字地址结构、网络字节顺序和地址转换功能

    介绍:应该用在网络编程实现每个套接字地址结构.所以主套接字地址结构后前提网络计划编制,地址结构可以在两个方向上发送:从工艺到内核和内核处理.构中的二进制值之间进行转换. 大多数套接字函数都须要一个指向 ...

  8. 【转】【Android UI设计与开发】第07期:底部菜单栏(二)Fragment的详细介绍和使用方法

    原始地址:http://blog.csdn.net/yangyu20121224/article/category/1431917/1 由于TabActivity在Android4.0以后已经被完全弃 ...

  9. python包

    有个伟人说过: python的学习很大一部分取决与你对第三方包的熟悉和掌握程度! virtualenv virtualenv用于创建独立的Python环境,多个Python相互独立,互不影响,它能够: ...

  10. 《剑指Offer》面试题-从头到尾打印链表

    题目描述: 输入一个链表,从尾到头打印链表每个节点的值. 输入: 每个输入文件仅包含一组测试样例.每一组测试案例包含多行,每行一个大于0的整数,代表一个链表的节点.第一行是链表第一个节点的值,依次类推 ...