软件编程低级错误:空指针.ppt_第1页
软件编程低级错误:空指针.ppt_第2页
软件编程低级错误:空指针.ppt_第3页
软件编程低级错误:空指针.ppt_第4页
软件编程低级错误:空指针.ppt_第5页
已阅读5页,还剩11页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

2020 3 26 PSST系统工程部C语言软件编程规范工作组 公司常见软件编程低级错误 空指针 前言 这套材料作为编程规范的辅助材料 帮助大家理解编程规范背后的原理 C和C 语言是我司的主流编程语言 然而C C 具有很多强大的语言特性 从而导致C C 非常复杂 使得代码更容易出现BUG 难以阅读和维护 业界知名的编程规范都对C C 容易出现问题的语言特性进行管理 例如MISRA 汽车工业软件可靠性联合会 制定的1998版的MISRAC规范指出 一些在C看来可以接受 却存在隐患的地方有127处之多 2004版的MISRAC规范将针对C语言的规则增加到了141条 对于程序员来说 能工作的代码并不等于 好 代码 好 代码的指标很多 包括可读性 可维护性 可移植性和可靠性等 出现网上问题的代码 大多数是不良编程习惯引起的 不遵守编程规范的代码 往往也是最不可靠的代码 本胶片收集了常见的空指针案例 给出了相应的纠正措施 申请内存没有捕获异常 问题描述 Web服务器返回500错误 问题定位 New内存失败 不会返回NULL 而会抛出异常 但代码中没有捕获这个异常 根本原因 C 语言中New内存失败后可以出现两种情况 一种是返回NULL 一种是抛出异常 可以在调用New函数时使用参数指定 也可以在编译选项中统一选择一种处理方式 项目组没有明确规定采用哪种处理方式 开发人员根据以前项目组的经验调用New函数后 判断是否非空 但在这个项目中即使New失败也不会返回NULL 举一反三 项目组必须规定统一的编程规范 维护老代码时 注意弄清楚老代码的设计和编程的规则 没有判断全局指针非空 问题描述 当主控板起来但接口板还没有起来时 使用命令undorule map删除所有的Rule map 出现DA异常 问题定位 在删除Rule map时 如果它引用了Link group 则将Link group中的pLink的引用计数减一 开发人员认为全局变量pLink永远不可能为NULL 所以没有判断其合法性 正常情况下 pLink确实不可能为NULL 但当系统重启时 先恢复了Rule map 在恢复Link group之前 pLink指针为NULL 此时如果从命令行删除所有的Rule map 就会出现DA异常 纠正措施 访问pLink之前 判断其是否为NULL 根本原因 多个模块相互配合时 可能出现千奇百怪的调用顺序 开发人员认为永远不可能为NULL的参数 实际网络中却很可能发生 举一反三 外部接口传入的参数 或其它模块维护的全局变量 使用之前必须判断是否合法 没有判断外部传入指针非空 问题描述 终端向服务器注册 服务器返回403失败响应 这时终端向服务器发送群组广告 服务core 问题定位 从core文件中看 是空指针引起 根据core文件中提供的的信息 反向检视代码 发现蓝色部分存在问题 对获取到的变量未做空指针判断 pSession SetUserContext pLogic GetPoCPCUUserContext 在用户未注册上时 服务器清空了资源 使得pLogic GetPoCPCUUserContext 取出来时为空 但传入方与接收方都未做空指针判断 导致出现问题 纠正措施 对传入的指针应做合法性检查IPoCPCUUserContext pContext pLogic GetPoCPCUUserContext If NULL pContext pSession SetUserContext pContext 举一反三 外部接口传入的指针 多个对象使用 很可能一方更改了 而另一方不知道的情况 使用之前必须判断是否合法 没有判断文件输入数据非空 问题描述 MM代码中使用了非法指针导致 空指针 服务器发生宕机 问题定位 从操作日志分析到MM分析list xml时出现宕机 hr pRootNode get firstChild 举一反三 外部文件读入的指针 可能为空 使用之前必须判断是否合法 没有判断文件输入数据非空 续 问题描述 在某省项目中 现场开发了与第三方的网管系统 以后简称E1 的接口程序 以后简称E2 用于接收网管上的所有实时告警信息 在不定期的情况下 接口程序E2会coredump 问题定位 从操作日志分析到读取第三方空日志文件时宕机FILE fp fopen writeAlarmLastTime log r charbuff 128 fscanf fp s buff 读取最新的告警时间 由于文件writeAlarmLastTime log为空 导致buff为空fclose fp longfileTime getAlarmTime buff 解析获取最新的告警时间 getAlarmTime函数未检查buff指针 纠正措施 在函数getAlarmTime检查指针的合法性或者检查fscanf的返回值 如果返回值为EOF 则返回if EOF fscanf fp s buff 读取最新的告警时间return 举一反三 外部文件读入的指针 可能为空 使用之前必须判断是否合法 定时器处理函数没有判断指针非空 问题描述 测试人员在测试过程中发现scf出现core 查看日志分析scf在收到CCA Term 消息时调用函数clearDiamCCATimer清除等待CCA Term 后 又进入处理定时器事件处理函数processDiamCCATimeOut 在该函数中出现core 问题定位 在如下场景中将会出现空指针引用导致core 1 收到CCA Term 消息 消息入队列2 定时器触发 定时器超时事件入队列3 处理CCR Term 消息 调用clearDiamCCATimer 清除定时器后 删除保存重发CCR消息的指针m pResendDiamCCR4 处理定时器超时事件 调用processDiamCCATimeOut 从m pResendDiamCCR中获取重发消息 TInterpretRTSCSM processDiamCCATimeOut pTmpDiamCCR TDiamScpCCR m pResendDiamCCR pMsgPara 当出现上面的场景时 此时m pResendDiamCCR为空 core 纠正措施 在函数processDiamCCATimeOut头部增加m pResendDiamCCR是否为空的判断if NULL m pResendDiamCCR return pTmpDiamCCR TDiamScpCCR m pResendDiamCCR pMsgPara 举一反三 注意定时器里面的指针 是否在其他任务里面被删除 指针初始化NULL 使用前没有检查 问题描述 山西电信客服坐席全部签出 问题定位 CTIServer发起资源连接时 如果发现两个连接方都已经存在有非会场的资源连接 则处理时存在有空指针访问 voidCSCP AnalysisConnectRequest CTI RESOURCE CONNECT Msg pMsg CConnectNode pNode CConference pOcuppyConf CConnectObject pObject NULL if pSourceObject NULLif pDevice lint e 413 if CONN CONF REQUEST pObject m ucCurConnectContext 使用指针时没有检查 导致使用空指针 pObject仅仅赋初始值NULL 没有真正赋值 pclint有空指针告警 被错误关闭 指针初始化NULL 使用前没有检查 续 纠正措施 变量的定义 初始化和使用要做到亲密无间 在首次使用之前定义和初始化变量CConnectObject pObject pDestObject if CONN CONF REQUEST pObject m ucCurConnectContext 举一反三 C99之前的C语言版本要求只能在作用域开始处定义变量 这种方式在C 中已经过时 这一限制的严重问题在于 在作用域开始时没有足够的相关信息进行初始化 因此我们只有两种选择 要么用某个默认的空值 比如例子中的NULL 来初始化 这通常是一种浪费 还回导致错误 要么让变量未初始化 而这是很危险的 解决方案很简单 尽可能局部定义变量 在需要首次使用前定义和初始化变量 空指针操作 多个条件一起判断 1 问题描述 测试接口时 如果没有输入必选参数 操作类型operationType 系统异常 问题定位 if operationType null operationType equals 1 分支操作 elseif operationType equals 2 分支操作 else 分支操作 表面上代码对空指针和各种取值都进行了判断 但是当operationType为null时 第一行的判断为FALSE 然后执行第二个判断分支 立刻出现空指针异常 其实 我们代码中经常会出现这样的低级错误 编码者第一次判断时思路很清晰 要对对象判空 但是以后想当然认为第一次已经判空了 elseif之后就不需要再次判断 纠正措施 见下页 空指针操作 多个条件一起判断 2 纠正措施 将判空作为单独的条件 这样代码虽然多了一行 却清晰了很多if null operationType 分支操作 elseif operationType equals 1 分支操作 elseif operationType equals 2 分支操作 else 分支操作 举一反三 将多条判断语句写在一起 非常容易出错 每一行代码最好只完成一个功能 空指针操作 写成了 问题描述 代码飞检发现下面代码 typedefmapMsgmap Msgmapm mapMsgData Msgmap iteratoritor m mapMsgData find nMsgID if m mapMsgData end itor itor second 问题定位 当m mapMsgData end itor为非 会继续执行 itor second 但此时itor为空指针 纠正措施 将 修改成 空指针操作 Map 取值自动添加空指针 1 问题描述 版本验证中 进行关闭 操作 引起coredump 问题无规律重现 问题定位 分析dump文件 导致coredump的代码是 if itRevTElink second GetLinkstat TELINK STATE DISCONNECT itRevTElink是从m mapIndexToLink中取出的 唯一可能的原因就是m mapIndexToLink中存在空指针 检视向map插入键值的代码 pCOSNTELinkpLink m mapIndexToLink pairLinkIndex link GetLocalNeID link GetLocalTeIfID if NULL pLink returnfalse 判断了键值为空 但直接返回 没有将这个空键值从MAP中删除 查看STL中实现map 的源码 发现使用map key 取值时 如果键值不存在 会自动插入一个节点 该节点键值为key 值则由默认构造函数自动生成 在上面代码中 自动插入了NULL值 造成后面引用了空指针造成coredump 纠正措施 见下页 空指针操作 Map 取值自动添加空指针 2 纠正措施 map取值时先用find进行查找 找到了再进行相关操作 In

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论