软件可靠性安全性技术.ppt_第1页
软件可靠性安全性技术.ppt_第2页
软件可靠性安全性技术.ppt_第3页
软件可靠性安全性技术.ppt_第4页
软件可靠性安全性技术.ppt_第5页
已阅读5页,还剩118页未读 继续免费阅读

下载本文档

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

文档简介

1,软件可靠性安全性技术,2,几个基本术语,故障(Fault) 差错(Error) 失效(Failure) 缺陷(Defect) 失误(Mistake) 隐错(Bug),3,软件质量的一个示例,在一段Visual Basic 6.0编写的程序Division中,从文本框1中输入数A#,从文本框2中输入数B#,计算C#=A#/B#从文本框3中输出,其程序如下: Public A#, B#, C# Private Sub Division() A# = Val(Text1.Text) 从文本框1中输入 B# = Val(Text2.Text) 从文本框2中输入 C# = A# / B# Text3.Text = Str(C#) 从文本框3中输出 End Sub A#=1,B#=0时结果如何?,exam1,4,软件可靠性,软件可靠性:在一定条件下软件实现所要求功能的能力。 关于软件可靠性的误区:软件对一组条件下的运行,如果是对的,则永远是对的,何有可靠性? 对软件可靠性误区的回答:对已认为满足了功能和性能要求的软件,为何有的软件在实际的运行中会经常出错?追其原因都是对运行中异常的操作、输入、事件无防范处理措施,诸如人机交互界面软件对误操作经常死机,通讯软件对外界干扰经常瘫痪等,这能说不是软件可靠性的问题吗?,5,软件可靠性的一个示例,前面的exam1就是一个示例。我们再给一个示例。用Visual Basic编写一个读入给定数据文件的程序。用户输入的文件名存放在text1.txt中,数据文件格式是:第一个数是整型数N(表明以下存放了N个浮点数),后续以空格、逗号或换行为区分符存放N个浮点数。OpenFile()子程序完成将数据文件中的N个浮点数读出存放在变量数组A#()中。,6,Private Sub OpenFile() Dim i, N Open Trim(Text1.Text) For Input As #1 打开数据文件 Input #1, N 读入数据个数 ReDim A#(1 To N) For i = 1 To N Input #1, A#(i) 读入数据 Next Close #1 关闭数据文件 End Sub 文件不存在或数据格式错误时结果如何?,exam2,7,软件安全性,软件安全性:对由于软件的缺陷造成人员伤亡、财产损失等危险事件的防范能力。 关于软件安全性的误区:软件只是代码程序和相应文档,软件结果只是对与错,何有安全性? 对软件安全性误区的回答:对实时嵌入式软件而言,软件的指令直接控制着硬件的动作,如果软件不对所控制硬件的指令进行安全性保护,有何信心保证系统是安全的?由于软件的错误造成重大财产损失、严重人员伤亡的实例已屡见不鲜,这能说软件没有安全性的问题吗?,8,软件安全性的实例,转塔设备的调转控制 ,9,软件可靠性安全性 设计准则,10,软件可靠性和安全性设计的一般性指导可参考 GJB/Z 102-1997 软件可靠性和安全性设计准则 Q/WE 871-1999 软件可靠性和安全性设计指南 二院制定的武器系统软件可靠性安全性设计准则,则是结合二院以往地空导弹武器系统软件中实际暴露的典型问题,总结整理归纳出的有关软件可靠性和安全性设计的具体细则,适用于二院武器系统软件开发中可靠性和安全性的设计。,11,4.4 圈复杂度的限制,12,圈复杂度问题的示例,圈复杂度115的控制流图,圈复杂度10的控制流图,13,4.5 余量的设计,应注意关键软件的余量设计,这些余量包括:存储量、IO通道吞吐量及处理时间等。在同步时间要求较高的系统中,处理时间的余量应不少于20%。如,某系统9ms通讯一次,则该系统的处理时间应小于7.2ms。 余量设计为我们在软件测试时使用一些在线动态测试工具,如CodeTest等,提供了必要的应用条件。,14,4.9.1 谨防实数取整的精度损失,实数取整的转换函数int()在C中是截取取整的,如果需要四舍五入,则必须特殊处理。 例如: float f = 1.9; int k; k = (int)(f); 则 k 是 1,而不是 2。,15,实数四舍五入后取整的方法,如果 f = 0, 则 int(f + 0.5) 是四舍五入后的取整结果; 如果 f 0,则 int(f 0.5) 是四舍五入后的取整结果。,16,4.11 安全关键信息码的设计,安全关键的信息码应采用具有检错能力的编码。 禁止对关键信息用一位的逻辑判别,如用“0”来表示“不起飞”,用“1”来表示“起飞”。对此具有检错能力的编码可以为用二位的逻辑判别,如用“01”来表示“不起飞”,用“10”来表示“起飞”。显然在有一位可能受干扰的系统假设下,用一位的逻辑判别无法检测其是否受干扰,而二位的逻辑判别则可以检测其是否受干扰,如“00”和“11”就表示信号受到了干扰。,17,安全关键信息码应用的实例,操作杆的误信号 ,18,4.10 异常计算的防范设计,在数值计算中,要充分考虑计算中的异常情况,如: (1)在除法计算中,要考虑除数为0或很小时的计算溢出的处理,可计算前先进行除数大小的判别检查; (2)在开平方根的计算中,要考虑被开根数是否大于等于零,可计算前先进行被开根数的符号判别。,19,异常计算设计问题的实例一,有效视线角误差 ,20,异常计算设计问题的实例二,21,4.13 接口数据的定义,在通讯接口数据定义时必须明确通讯的数据量、数据格式、数据内容、换算要求、传输协议、传输率、误码率。 (1)初始状态要设计为0位状态。如,“00表示状态未定”即应为初始状态。又如,用2位表示的:“01表示状态1”、“10表示状态2”、“00表示状态未定”,和用1位表示的:“0表示状态1”、“1表示状态2”,对初始状态的理解是不一样的。,22,(2) 对交换字各位解释说明其含义时,单一位的解释说明,不仅要说明为“1”的含义,还要说明为“0”的含义;多位解释说明时,不仅要说明特定组合的含义,还要说明其它组合的含义。如2位组合的含义解释说明时,不仅要说明“00表示状态未定”、“01表示状态1”、“10表示状态2”,还要说明“11”表示何含义(可能是无意义,但要明确说明,有些是不需要处理而保持以前状态,有些是要进行报警或异常错误处理的)。,23,4.15 异常处理的设计,对软件的编程不能只考虑正常情况下的处理,还应充分考虑可能的异常事件的处理。在软件的设计过程中应专门对可能的异常事件进行分析,这一工作称之为“软件失效模式及影响分析”。,24,如,在对数据文件操作时可以考虑的异常事件有: (1) 错误的文件名或文件数 (2) 文件没找到 (3) 错误的文件模式 (4) 文件已经被打开 (5) I/O设备错误 (6) 文件已经存在 (7) 错误的记录长度 (8) 磁盘满 (9) 超过文件结尾的输入 (10)错误的记录数 (11)错误的文件名 (12)太多的文件 (13)设备不可使用 (14)权限不允许 (15)磁盘没准备好 (16)不能对不同设备重新命名 (17)路径或文件访问错误 (18)没找到路径,25,显然这18种模式无需也不必都考虑,可依据实际情况裁剪考虑。如在人机交互软件中用户选择数据文件,则“错误的文件名或文件数”、“文件没找到”和“路径或文件访问错误”是必须要考虑的,需要对此设计相应的处理方法。 如果是具有运行错误陷阱功能的高级语言,如:VB、VC、Ada等,则错误陷阱的使用是很好的方法。无可靠性措施的软件:如当输入的文件不存在时,软件运行被异常终止。用户不知所措,甚至连相关信息都没得到。软件失控了! 有可靠性措施的软件:如当输入的文件不存在时,软件提示输入文件不存在的信息,并重新返回到用户输入状态,等待用户终止输入过程,或重新输入。软件始终处于受控!,exam3,26,4.17 变量的命名,变量命名要清晰。通常的命名有头字母大写命名法和下划线命名法。 头字母大写命名法如:InitialValue,ObjectPosition等。下划线命名法如:initial_value,object_position等。现在又流行带类型说明的头字母大写命名法:如intInitialValue表明是int的类型,flObjectPosition表明是float的类型,而用tempInitialValue来表明其是一个临时变量。 变量的命名对程序的理解及维护起着非常重要的作用。,27,变量命名问题的实例,for(tchflag=0;tchflag14;tchflag+) ,28,4.19 变量的初始化,所使用的变量要有明确的初始化,避免使用缺省的初始值。同时,对循环处理过程的变量初始化要特别注意。,29,变量初始化问题的实例一,固化与非固化的差异 ,30,变量初始化问题的实例二,双发时的过程标志 ,31,4.21 多组条件判别的完全性,C语言中的IF语句推荐的书写格式为 if ( id=0 ) /0的处理; else if( id=1 ) /1的处理; else /其它情况的处理; 注意这里else要求明确写出,要充分利用else进行异常情况的处理。事实上,if处理条件的遗漏是经常发生的,需要特别小心。,32,多组条件判别不完全性的实例,if(mo0 else /此处进行提示报告 ,33,4.22 函数调用返回的设计,函数的返回必须要有运行状态的标识,以使调用者能识别被调函数的运行状态。,34,函数调用返回设计的示例,方法一:可以设置整型函数的返回值,以标识函数的运行状态。如计算三角形面积的函数可设计为:,int TriangleComp(float a, float b, float c, float *s) if () /正常时的计算,面积值赋给*s return(0); else if () /出现边长小于零的情况 return(-1); else if () /两边之和小于第三边的情况 return(-2); else /其它情况 return(-10); ,int flag; flag= TriangleComp(3,4,5, if (flag0) /异常处理 else /正常处理 ,在调用时可以进行判别,35,方法二:可以在调用参数中专门设计一个函数运行状态的参数。如上述计算三角形面积的函数也可设计为:,float TriangleComp(float a, float b, float c, int *e) float s; if () /正常时的计算,面积值赋给s返回 *e = 0; return (s); else if () /出现边长小于零的情况 *e = -1; return (0); else if () /两边之和小于第三边的情况 *e = -2; return (0); else /其它情况 *e = -10; return (0); ,int e; float s; s = TriangleComp(3,4,5, if (e0) /异常处理 else /正常处理 ,在调用时可以进行判别,36,4.23 函数调用参数的匹配,函数调用的参数类型、次序和个数必须匹配。类型的匹配一是注意int、float、double、char等类型的匹配,二是注意指针地址和地址内容的匹配。如,int func(float *)的函数,直接调用func(0),则func使用的是0地址单元中的值,而非0值,如要送0值则应先申请“float angle=0;”再调用func(&angle)。,37,函数调用参数匹配问题的实例,回路测试 ,38,4.28 对GOTO语句的限制,原则上限制使用跳转(GOTO)语句,在使用GOTO语句能带来某些好处的地方,一定要控制GOTO的方向: 只允许向下GOTO,不允许向上GOTO; 只允许从循环中GOTO出去,不允许GOTO到循环中来。 但在即将颁布的国军标中将严格禁止GOTO语句的使用。,39,4.29.2 中断的嵌套,中断嵌套分自嵌套和外嵌套。自嵌套就是被自身中断嵌套,外嵌套就是被其它中断嵌套。 中断的使用除特殊需要外一定要避免嵌套,常用的方法就是进入中断服务程序后关掉不希望嵌套的所有中断。 自嵌套一定要避免; 必要时的外嵌套要充分考虑中断优先级的影响; 允许中断和禁止中断的语句位置要独立进行仔细分析。,40,4.29.3 中断的返回,除特殊需要外一定要避免从中断服务子程序中使用跳转语句直接出去,应当使用正常返回语句。因为直接跳出一是影响了堆栈的控制,二是可能破坏跳转处的应有状态。,41,4.29.4 中断的现场保护,要充分考虑到中断任何时刻都可能发生的特点,保存好需要保存的现场,并在中断服务子程序返回时正确恢复现场。如在主程序中有的程序段是禁止带符号位运算,有的程序段是允许带符号位运算,而中断服务子程序中需要带符号位运算,则在中断服务子程序返回时一定要恢复到中断响应时的禁止或允许带符号位运算。,42,4.29.5 不用中断源的屏蔽,不用中断源一定要进行屏蔽。 不用中断源的软屏蔽应通过编写空处理的对应中断服务子程序来实现。,43,不用中断源无空中断服务子程序的实例,Int03中断不用后,残留允许打开语句,但删除了Int03的中断服务子程序 ,44,4.29.6 注意对误中断和漏中断的防范,在中断的使用中,除了要遵循一般的可靠性安全性设计准则外,还应该重点对每一中断的两个故障模式进行认真分析。这两个故障模式是:误中断和漏中断。通常是在程序中设计一些特征标识量,在中断响应服务子程序中应首先检查相应的特征标识量,以防误中断。在一些依赖于中断响应服务子程序执行结果的关键处理程序中,应首先检查相应的特征标识量,以防漏中断。 在软件的概要设计阶段,应认真分析哪些处理过程是不能被中断打断的,必须以清单方式列表。对这些处理过程应在相应程序执行前关闭中断源,执行完后再打开必要的中断源。,45,误中断的实例,上传程序被中断打断 ,46,漏中断的实例,多通道异步并发 ,47,防漏不防误,防漏又防误,48,4.30 看门狗的设计,看门狗技术是控制运行时间的一种有效方法。看门狗实际上是一种计时装置,当计时启动后看门狗在累计时间,当累计时间到了规定值时触发到时中断(即狗叫),看门狗在不需要时可以关闭。看门狗的设计要首先明确其目的性。如: (1)要防某段程序可能的死循环,则在此段程序前启动狗,在此段程序后关闭狗,在狗叫中断中进行超时异常处理。 (2)要防外来的信息长时间不来,则在开始等外来信息时启动狗,在接收到外来信息时关闭狗,在狗叫中断中进行超时异常处理。 (3)要防计算超时,则在开始计算时启动狗,在计算完毕后关闭狗,在狗叫中断中进行超时异常处理。 显然,不可能要求一个狗可以看管好所有的超时情况。,49,看门狗设计问题的实例一,这里,狗叫可能是因为程序某处选入死循环,可能是外来信息长时间不来,也可能是处理信息超时。如果这里设计的定时器是为了检测与外系统的通讯是否出现异常为目的(如规定18ms未来信息表明通讯异常),显然如此设计就有所欠缺。,50,看门狗设计问题的实例二,总线占用超时控制 ,51,4.31 避免潜在的死循环,在等待外部信号的程序段中,不允许无限制地等待。正确的做法应是,或采用循环等待次数控制,或使用定时器,使得规定时间内(无论成功或失败)必须保证退出等待外部信号的程序段。,不允许的设计方法,建议采用的设计方法,52,4.35 注意通过双口RAM进行握手,通过双口RAM进行信息交换是设计师经常采用的一种设计方案。的确双口RAM提供了信息交换双方的方便读写,但仅靠双口RAM要做到读写的时序要求就要格外小心。 如此的设计是要避免的:通过双口RAM交换信息,在双口RAM中设置了握手信号单元。读方检查到握手信号为01H,表明对方已准备好数据,再读数据,读完后将握手信号置为00H;写方检查到握手信号为00H,表明对方已取走数据,再写数据,写完数据后再将握手信号置为01H,表明自己已准备好数据。,53,这种设计不一定可靠,可能会出现写方要写握手信号时,读方正在读握手信号,则写方要写的值写不进去。可靠的设计应用硬件连线保证握手,而不要靠双口RAM中的握手信号。如果一定要靠双口RAM进行握手,则写握手信号单元数据时一定要写完后接着再读出,经验证确实写成功后再进行下面的操作,否则需继续写。 当然这必须与避免潜在的死循环的设计准则联合使用。,54,可靠的设计方法,握手标志置不上的可能,55,4.36 数据采集的多路冗余设计,关键数据的采集可采用多路冗余设计,即可以从多个通讯口对同一数据进行采集,通过表决进行有效数据的裁决。通常多采用奇数路的冗余设计,如3路、5路等。 (1)开关量的裁决可采用多数票的裁决,如3取2、5取3等。 (2)模拟量的裁决可采用中间数平均值的裁决,如3路数的中间值、5路数去掉最大最小值后的平均值等。,56,关键数据的采集可采用多次冗余设计,即可以从同一通讯口多次对同一数据进行采集,通过表决进行有效数据的裁决。通常多采用奇数次的冗余设计,如3次、5次等。 (1)开关量的裁决可采用多数票的裁决,如3取2、5取3等,也可采用连续次数的裁决,如5次里连续3次的量被才被认可,当然这种裁决被认可量比简单的5取3裁决更严格。 (2)模拟量的裁决可采用中间数平均值的裁决,如3次数的中间值、5次数去掉最大最小值后的平均值等。,57,极关键数据的采集亦可采用多路多次的综合冗余设计,即可以从多个通讯口对同一数据进行多次采集,通过表决进行有效数据的裁决。 附注:(m+1)/(2m+1)冗余措施失效率的计算 假设一个过程的失效率是,在2m+1个相同功能的过程中取m+1个相同的结果作为最终结果,这种措施称为(m+1)/(2m+1)冗余措施,在不考虑共因失效的前提下,其失效率为,58,4.37 时间飘逸的防范,59,4.38 TMS320C25的初始化,采用辅助寄存器对4号单元进行初始化置位,在常温下是可以的,但在低温条件下(小于-5)将会出现问题。对4号单元进行初始化置位必须采用直接寻址的方式。,60,软件可靠性安全性 C语言编程准则,61,1998年,国际汽车工业软件可靠性协会MISRA组织制定了“汽车软件C语言使用指南”的标准。这份标准的产生在自动化行业极大地推动了使用“安全的C”进行编程。这份标准在汽车行业被广泛接受,同时它也被其它行业所广泛借鉴。 利物浦数据研究协会LDRA作为专业软件测试协会建立于1975年。LDRA Testbed软件测试工具可基于MISRA的C语言使用标准对C语言程序进行检查,以帮助用户们在程序代码上加强行业标准的执行。 在我国,2005年颁布实施了GJB 5369-2005,航天型号软件C语言安全子集。,62,Q/WE 905-2005 导弹武器系统C语言安全子集,本标准完全遵循GJB 5369-2005, 航天型号软件C语言安全子集,并在二院型号软件工程实践的基础上,新补充了22条强制性准则和2条推荐性准则,将GJB航天型号软件C语言安全子集中的一条推荐性准则上升为强制性准则。附录B是相对于GJB航天型号软件C语言安全子集新增加的附录。,63,准则分类,(1) 声明定义类 (2) 版面书写类 (3) 分支控制类 (4) 指针使用类 (5) 跳转控制类 (6) 运算处理类 (7) 过程调用类 (8) 语句使用类,(9) 调用返回类 (10) 程序注释类 (11) 循环控制类 (12) 类型转换类 (13) 初始化类 (14) 比较判断类 (15) 名称、符号与变量使用类,64,4.1.1.15 字符型变量必须明确定义是有符号还是无符号,void static_p(void) char c = c; /* . */ ,违背,65,4.1.1.20 禁止在#include 中使用绝对路径名,#include void Dummy(void) /* . */ 头文件路径应该在编译器的选项中予以设置说明,违背,66,4.2.1.2 循环体必须用大括号括起来,int static_p(int p_1) int j = 10; int k = 0; /* . */ for (k = 0; k 10; k = k + 1) j=j+1; return j; ,违背,67,4.2.1.3 then/else中的语句必须用大括号括起来 (二院简化为: else中的语句必须用大括号括起来),int static_p(int p_1, int p_2) int i = 1; int j = 2; /* . */ if (p_1 0) i = i - 1; else i = i + 1; return i; ,违背,68,4.2.1.4 逻辑表达式的连接必须使用括号,void static_p(void) bool flag = true; unsigned int y = 0u, x = 0u, z = 1u; /* . */ if (x 0 | z + y != 0 ,违背,69,4.2.1.5 禁止在头文件前有可执行代码,void static_p(void) #include “myfile.h“ /* . */ ,违背,70,4.2.1.6 宏参数必须用括号括起来,#define static_p(x) x = 0 ? x : -x void test_p(void) unsigned int result; int a = 6, b = 5; /* . */ result = static_p(a - b); result = static_p(a) + 1; /* . */ ,违背,71,4.2.1.7 嵌入汇编程序的过程必须是纯汇编程序,void static_p(void) unsigned int x; x = 0u; _asm mov eax, x ,违背,72,4.2.1.9 禁止字符串中单独使用“”而非“0” (二院进一步明确为: 4.2.1.9 字符型数组赋值时,必须使用“0”终止字符串),void static_p(void) unsigned char str5; str0=a; str1=b; str2=c; /* 其它处理 */ ,违背,73,4.3.1.1 禁止条件判别成立时相应分支无执行语句,void static_p(void) unsigned int value_x = 1u; /* . */ if (value_x = 0u); /* . */ if (value_x = 0u); ,违背,74,4.3.1.4 在switch语句中必须有default语句,如果switch语句中缺省了default语句,当所有的case语句的表达式值都不匹配时,则会跳转到整个switch语句后的下一个语句执行。强制default语句的使用体现出已考虑了各种情况的编程思想。,75,4.3.1.7 禁止switch的case语句不是由break终止,如果某个case语句最后的break被省略,在执行完该case语句后,系统会继续执行下一个case语句。case语句不是由break终止,有可能是编程者的粗心大意,也有可能是编程者的特意使用。为了避免编程者的粗心大意,因此禁止switch的case语句不是由break终止. 二院的调整:原则上禁止switch的case语句不是由break终止,当确实是编程者的特意使用时,必须加以“/* 此情况属于部分的case共用 */”的明确注释。,76,4.4.1.2 指针的指针不能超过两级 (二院进一步明确为:4.4.1.2 禁止指针的指针超过两级),对指针进行控制是很困难的,当指针的指针超过两级时,使用起来更是具有风险,因此禁止指针的指针超过两级。 二院的细化:当在某种特殊情况下确实需要超过两级的指针时,必须加以“/* 详见详细设计报告的指针特殊设计 */”的明确注释,在详细设计报告的指针特殊设计中详细说明理由,并在单元测试报告中提供针对性的测试结果。,77,4.6.1.15 禁止在逻辑表达式中使用赋值操作符 (二院进一步明确为: 4.2.1.15 禁止在条件判别语句中使用赋值操作符),void static_p(void) unsigned int z = 0u, x = 0u; bool flag = true; /* . */ if (flag = false) z = x - 1u; /* . */ ,违背,78,4.6.1.2 数组的使用必须保证不会出现越界,void static_p(void) unsigned int a4; /* . */ a4 = 1; /* . */ ,违背,79,4.6.1.7 位的定义必须是有符号整数或无符号整数,struct static_p unsigned char x:1; void dummy(void) /* . */ ,违背,80,4.6.1.8 禁止给变量赋的值与变量的类型不一致,void static_p(void) unsigned int d; d = 2.0; /* 应该使用 2u */ /* . */ ,违背,81,4.6.2.2 谨防长度操作符sizeof的副作用,长度操作符sizeof不计算操作数的值,所以更明确的要求是:禁止在sizeof中使用赋值。,void static_p(void) unsigned int x = 1u; unsigned int y = 2u; int a = 3; /* . */ a = sizeof( x=y ); ,违背,82,4.6.2.4 避免由于设计的原因导致某些代码不能执行,#define defval 0 void static_p(void) if (0) /* . */ if (defval) /*.*/ ,违背,83,对程序文件的限制,4.2.2.1 建议一个文件中的程序总行不超过2000行 4.2.2.2 建议一个过程或函数中的程序总行不超过200行 4.7.1.3 static类型的过程在所在文件中必须被调用,84,4.8.1.1 禁止使用容易混淆的语句 (二院进一步明确为: 4.8.1.1禁止单独使用小写字母“l”或大写字母“O”作为变量名 ),void static_p(void) int l = 1, O = 0; /* . */ l = O; O = l; ,违背,85,4.8.1.4 禁止使用不起作用的语句 (二院补充),void static_p(void) unsigned int x = 0u; x; ,违背,86,函数返回的限制,4.9.1.1 函数必须有返回语句 4.9.1.2 禁止void类型的过程中的return语句带有返回值 4.9.1.3 有返回值的函数中return必须带有返回值 4.9.1.4 函数返回类型必须一致,87,4.10.1.1 禁止使用嵌套的注释,void static_p(void) /* This is the Outer Comment /* This is the Inner Comment */ ,违背,88,4.11.1.2 循环变量必须是局部声明的,unsigned int global_f = 0u; int loop_standards(int p_1) int j = 10; /* . */ for(global_f = 0; global_f 10; global_f +) j-; return j; ,违背,89,4.13.1.4 变量使用前必须被赋过值,在使用变量前应确保变量曾被赋过值。例如: unsigned int x; unsigned int y; y = x; 其中对变量x的使用,在使用前未曾被赋过值。 如果变量是在某些条件前提下进行的赋值,在条件结束后使用该变量,则同样是违背该条准则。,90,4.14.1.1 禁止对实数类型的量做是否相等的比较,void static_p(void) float f1, f2; f1 = 1.01f; f2 = 2.01f; /* . */ if (f1 = f2) /* . */ if(f1 = 0.0f) f1 = f1 + 0.01f; ,违背,91,4.15.1.2 禁止局部变量与全局变量同名,C语言编译器是允许局部变量与全局变量同名,但局部变量的作用域只限制在声明的模块内部。为避免本意是需要对全局变量更新,但由于存在同名的局部变量,导致全局变量未得到实际有效的更新,因此禁止局部变量与全局变量同名。,unsigned int Fire_Command; void static_p(void) unsigned int Fire_Command = 2u; ,违背,92,“4.14.1.1 禁止对实数类型的量做是否相等的比较” 实验说明,如下代码: int P=1000; float d=0.435f; int H=435; if (H=(P*d) /* 违背了准则*/ i=1; else i=2; 到底走哪个分支?,走此分支?,exam4,H=435 P*d=1000*0.435=435 是否相等?,93,“4.2.1.6 宏参数必须用括号括起来” 实验说明,如下代码1: #define p(x) x = 0 ? x : -x int result; int a = 6; result = p(a) + 1; result到底等于几?,如下代码2: #define p(x) (x = 0 ? x : -x) int result; int a = 6; result = p(a) + 1; result到底等于几?,result=6还是7?,exam5,94,“4.6.2.2 谨防长度操作符sizeof的副作用” 实验说明,如下代码: int x = 1; int y = 2; int a = 3; a = sizeof(x=y); x到底等于几?,现在x=1还是2?,exam6,95,编程准则违背的 典型实例,96,“4.8.1.4 禁止使用不起作用的语句” (二院补充) 的典型实例,该准则在某软件中以“x-0;”的形式违背了,而经过确认是由于编程人员误将“x=0;”的“=”号写成了“-”号所致,其结果是导致变量x的赋值失败。,97,“4.6.1.15 禁止在条件判别语句中使用赋值操作符” 的典型实例一,该准则在某软件中以“if(the_i=5)”的形式违背了,而经过确认是由于编程人员误将“if(the_i=5)”的“=”写成了“=”所致,其结果是该判别条件无论变量the_i为何值都将执行该分支的处理。,98,“4.6.1.15 禁止在条件判别语句中使用赋值操作符” 的典型实例二,在某软件中有如下语句: if(uiSendLen = 0x55AA) & (uiRecvLen = 0x66BB) & (uiBaud = 0x77CC) 其中将条件(uiBaud=0x77CC)判别误写为(uiBaud=0x77CC)的赋值,后果是即使uiBaud不为 0x77CC,其他条件满足仍能走入真分支。,99,“4.14.1.4 逻辑判别表达式如果存在运算项, 必须要使用括号” (二院补充) 的典型实例,该准则在某软件中以“if(tbc&0x80=0x80)”的形式违背了,导致当tbc=0x80时条件判别走不成立的分支。正确的写法应该是“if(tbc&0x80)=0x80)”。,exam7,100,“4.12.1.2 禁止对指针变量赋值类型不匹配” (二院补充) 的典型实例,在某软件中,变量定义如下: unsigned long *p; unsigned char q50; 程序中有如下的使用: p = ,101,“4.2.1.4 逻辑表达式的连接必须使用括号” 的典型实例,在某软件中 if(S10.Coun=1)|(S11.Coun=1) &(B3Leav = 7) 从程序结构上猜想,应该是: 在 (B3Leav = 7) 条件下, 或 (S10.Coun=1) 或 (S10.Coun=1) 如果是此,就应该 if(S10.Coun=1)|(S11.Coun=1) &(B3Leav = 7) ,102,“4.6.1.9 赋值类型必须匹配” 的典型实例,在某软件中ADData是定义为signed char类型,程序中: ADDatai=(signed char)*AD402; /* 读12位带符号的AD采样值 */ ADDatai=ADDatai 在标准C中,signed char类型变量是8位的,有效范围-128,127,对8位变量赋12位数值在标准C中是取后8位。ADData应定义为int类型。,103,“4.6.1.2 数组的使用必须保证不会出现越界” 的典型实例,在某软件中是如下定义的: unsigned char Ykd6; 但程序中是如下使用的: for (n=0 ; n7 ; n+) Ykdn = 0x0 ; 按定义,Ykd只有6个元素,即Ykd0、Ykd1、Ykd5,而是使用中却用到了Ykd6。,104,“4.14.1.5 禁止对无符号数进行大于等于零 或小于零的比较” (二院补充) 的典型实例,在某软件中有如下语句: unsigned long s_addr; s_addr=(unsigned long)hostGetByName(compName); while (s_addr=ERROR) ERROR在vxWorks.h被定义为-1,用unsigned long类型数与ERROE进行比较总是不成立的。,105,“4.13.1.4 变量使用前必须被赋过值” 的典型实例,在某软件中, void Para_check() int k; while(k 4) k+; 显然对变量k未赋初值就进行while(k 4)的使用。k未赋初值并不意味着就等于0,有可能是一随机数。在某台式机的VC 6.0中,k的初值为0xcccccccc,此时while(k 4)上来就不满足。,106,“4.13.1.4 变量使用前必须被赋过值” (二院的细化:4.13.1.4(1) 变量使用前必须被赋过值 (禁止只是条件赋值)) 的典型实例,在某软件中有如下语句: int test_start(v

温馨提示

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

评论

0/150

提交评论