⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 195.txt

📁 SVM(支持向量机)和EM(最大熵)文本分类算法
💻 TXT
📖 第 1 页 / 共 5 页
字号:
【处理过程】:处理过程如下:
#define     MOD128          127  //队列长128,当队头到128时,上其返回。
#define    W_MOD           127 //发送窗口队列,意义同上。
在函数L2_TO_L1()中,有如下语句:
        linkstate_ptr->SendWin.head = (head + 1) % W_MOD ;
这里当head=126时,SendWin.head = 0,这将造成发送窗口指针和队列窗口指针错位,造

成链路复位;
另外,在重发函数void INVOKE_RETRANSMISSION(_US logic_link,_US n_r)中,有如下语

句:
        retran_num = (LinkState[logic_link].Vs + MOD128  - (_UC)n_r) %  MOD128

 ;
        w_head = (LinkState[logic_link].SendWin.head + W_MOD  - retran_num) % 

W_MOD ;
第一个语句求欲重发的消息包个数,第二个语句求重发的起始位置,当Vs小于n_r时,将造

成实际重发数小于欲重发数,同时造成实际起始重发位置和欲重发起始位置错开,从而引

起链路复位。上面三个语句应该做如下改动:
        linkstate_ptr->SendWin.head = (head + 1) & W_MOD ;

        retran_num = (LinkState[logic_link].Vs + MOD128  + 1 - (_UC)n_r) &  MO

D128 ;
        w_head = (LinkState[logic_link].SendWin.head + W_MOD + 1 - retran_num)

 & W_MOD ;
【结  论】:由于链路通信对系统效率要求很高,算法采用效率最高的,但位与(&)和求

模(%)这小小的区别,造成的竟是链路复位这种严重的错误。

【思考与启示】:对这类问题,大家在阅读代码或代码审查时一定要注意,仔细一点往往

能发现问题,但在测试中来定位这种问题,花费的时间往往更长。

6、注意数据类型的匹配
【案例1.6.1】
【案例描述】
	下面通过测试中的一个例子来说明这个问题:命令DSP N7C是用来显示NO7电路状态的,其

参数设备类型DID支持TUP和ISUP,参数信道号BSN支持多值输入(最多支持32路查询),正

常情况下该命令没有问题。但试了非正常情况下,问题就出来了。
	1、首先试BSN参数越界情况,即参数BSN超过32路查询,选了几个数据段,问题就出来了

。对于0&&300和0&&256,该命令返回结果不一致,对前者认为参数越界,对后者返回执行

成功。
	2、对于参数DID,选定一种设备类型(TUP或ISUP),让参数BSN所包含的32路电路跨越T

UP和ISUP,两次结果是不一致的。
【处理过程】
	反馈到开发人员那里,第一个问题是BAM的问题,第二个问题是SM的问题。
【结  论】
	1、为数据超出范围溢出造成,int值赋值给BYTE,造成数据丢失。
	2、问题的产生是因为查询的第一个信道是TUP电路,但是却按ISUP电路查询。ISUP的维护

处理函数判断第一个信道不是ISUP信道,认为整个的PCM不是ISUP类型的PCM,返回全部的

电路状态为未安装。消息处理不合理。TUP也会产生如此错误。

【思考与启示】
	我们的MML命令并不是无懈可击的,许多表面上的小问题,往往隐藏着代码的缺陷和错误


【案例1.6.2】
【正            文】
当我们使用PC-LINT检查代码时,会发现大量的数据类型不匹配的告警,大部分情况下,这

种代码上存在的问题并不会引起程序功能实现上的错误,但有些情况下,也许会产生严重

的问题:

       一、不同数据类型变量之间赋值引起的问题,实际上,该类问题也可以分为几种情

况:
1、直接赋值,比如,把一个WORD型变量赋给一个INT型变量,如果WORD型变量大于32767,

INT型变量得到的就是一个负值了。 
【例一】一次测试过程中发现,SDH送的告警在BAM调试窗口打印出红色提示:File(XXX),

Line(XXX):Invalid alarm id ,from: 7, AlarmId: 65463
经过检查数据发现,并没有ID为65463的告警,分析上报的数据帧,发现上报的告警ID为B

7,原来代码中有一处强制类型转换:
            sdhAlmStru.AlarmId = (WORD)RecvBuffer[iTmpLen + 5];
char型强制转换成WORD型。B7就变成了FFB7,十进制就是65463。由于char是有符号型,B

7的第8位为1,所以转换后为FFB7,而不是代码作者希望的00B7,如果第8位是0,或该变量

是BYTE型,转换就不会有问题了。
2、函数形参和实参不一致,实际上和第一种情况本质上是一样的,只是表现的形式不太一

样,这种情况也是代码中经常出现的问题,下面例子是测试中曾经发现的一个小问题:
【例二】在file01中的INT DebugMsgProc(char byMsg0, char byMsg1)函数,两个形参都

是char型,而实际传入的参数都是BYTE型,结果函数中的如下语句:
PrintfE(PID_RED," %d ticks time out!",byMsg1);
在byMsg1大于127时,输出错误的结果。

    二、不同数据类型之间的比较操作

在循环终止条件的判断中,不同类型变量的比较操作是容易造成死循环错误的地方,同时

也是开发人员容易忽视的地方,值得测试人员多加留意。下面两个例子是该类错误的两种

典型情况:
【例三】file02文件中某函数中如下代码,可能造成死循环:
         ......
            int i;
	WORD *pCheck  =(WORD*)p;
	WORD wCheckSum=*pCheck;
	pCheck++;

	for(i=1;i<dwLen/2;i++)
	{
		wCheckSum^=(*pCheck);
		pCheck++;
	}
	//binlen had already word alignment
	return (wCheckSum);		
	......
   该段代码是在DOS环境下用BC编译的,由于循环变量i是int型(2个字节),而dwLen是

DWORD型(4个字节),如果dwLen大于65536,那么该函数就是死循环了。

上面的例子是不同类型变量之间直接比较操作,还有一种情况是函数的返回值与另一不同

类型的变量比较,见下面例子:
【例四】file03.c文件中某函数中如下代码,
     		while( ftell(fp)< Part[3])
		{.....
                         }	
  ftell返回long型,而Part是DWORD型,有符号变量和无符号变量的比较,可能造成死循

环。

类似的例子还有很多,类型不匹配的问题还有许多种情况,都是代码中的隐患,有时会造

成严重的后果,需要引起足够的重视。对于该类问题,我们可以利用PC-LINT工具对代码进

行细致的检查。

7、用于控制条件转移的表达式及取值范围是否书写正确
【案例1.7.1】
【案例描述】:
	在测试主机MPU板倒换功能时,如果MPU备份充分,倒换前后对处于激活状态的电路应无影

响,即不影响通话。但近期测试发现,如果两局通过DT板进行一号对接,MPU备份倒换却发

生断话。具体现象为:如果DT板的第1个PCM系统电路为故障,则MPU倒换时复位该DT板,如

果DT板的第2个PCM系统电路为故障,则MPU倒换时复位下一块DT。

【处理过程】:
	据查,MPU倒换时会自动复位处于“故障”态的电路,但由于计算错误(多加了32),错

复位了下一个PCM系统32路电路。
【结  论】:
	如此严重问题为什么到今天才发现?因为我们在实验室中一般采用同一单板的2个PCM系统

自环进行测试,则不会在某单板上有故障和空闲电路共存,自环屏蔽了错误。
【思考与启示】:
	自环是在测试环境下常用的一种提高效率的手段,但一旦条件允许,我们的测试工作应尽

量模拟网上的实际环境进行。

【案例1.7.2】
	平时对计费功能进行测试的时候,浏览详细话单都是比较注意话单本身的正确性,并没有

注意该命令对系统的影响。所以当浏览少量话单的时候,并没有发现该命令的异常。但是

当时间的跨度较大时,详细话单数量较多,问题就出现了。执行如下命令:
	LST AMA: TP=NRM, SD=1999&7&1, SA=YES;
	当浏览了大约10万张详细话单后,终端与BAM的连接关闭。重建连接后,发现话单台的命

令不能执行。观察BAM的性能,发现话单台仍占有CPU50%以上的利用率,说明原来的任务仍

在执行。需要关一下话单台才能恢复正常。
	重复上述步骤,当终端与BAM的连接尚未关闭时主动断开此次连接,结果同上。
	反馈到开发人员那里,发现该现象与设计的初衷是相违背的。本来话单台控制最多输出2

00张话单,这是为了防止过多话单的输出显示会增加BAM的开销,从而降低BAM的性能。查

看一下源代码,问题就发现了。
	话单台控制最多输出200张话单
程序如下
    while(timeCur <= timeEnd)
    {
	timeCur += tsOneDay;//加一天

	while(fileBill.Read(&rpt, sizeof(CBillReport)) == 
		sizeof(CBillReport))
	{
                 .....................	
                         //只输出满足条件的前200张话单
	         if (++wBillCount == 200)
	        {
		break;
	        }
	}//一个文件查询结束
   }//所有文件查询结束

	在话单输出200张之后,程序只退出一层循环,仍然会从下一天话单继续输出,导致向MM

L发帧过多,造成MML和话单台都被堵死。
	修改ProcessQueryBill()函数
     //只输出满足条件的前200张话单
     if (++wBillCount == 200)
     {
         	timeCur = timeEnd + tsOneDay;//退出第二层循环,
		while(timeCur <= timeEnd)
			break;
     }        
	作上述修改后问题就不再出现了。
	一些MML命令从完成的功能来讲可能是没什么问题的,但其执行对系统性能的影响我们在

测试时时往往给忽视了。在我们目前的BAM方案中,存在着多个终端协同工作,如果某个终

端发出的命令在BAM中长时间独占着大部分系统资源,造成的后果是严重的。这是在设计时

要避免的,在测试中要注意的问题。

【案例1.7.3】
【正            文】
	在判断模拟用户端口是否反极性时有这样一段程序:  
      	if ( ( bsn >= g_wASL32StartPSN ) && 
           ( ( ( bsn - g_wASL32StartPSN ) % 32 ) == 15  ||  ( ( bsn - g_wASL32

StartPSN ) % 32 == 16 ) ) )
			return TRUE;
 	if ( ( bsn % 16 ) == 7 || ( bsn % 16 ) == 8 )
			return TRUE; 
	 	return FALSE;

	作者的本意是如果是32路用户板(蓝色字体判断),就看端口号是否是第15和16路,如果

是,就是反极性端口,返回TRUE,否则就不是,应该返回FALSE。但代码表达的意思是:如

果是32路用户板并且端口号是15或16就返回真值,否则还要执行下边语句。
	当端口在32路用户板上,但端口号不是15或16时,不同的32路端口的起始地址g_wASL32S

tartPSN,会导致不同的非15、16端口被误认为是反极性端口。举个例子,当g_wASL32Sta

rtPSN的值为3000时,端口号为3000(第一块板上的第0个端口)就被认为是反极性端口,

这与作者的意图完全相悖。
	可以将代码修改如下:  
    	if ( ( bsn >= g_wASL32StartPSN ) 
		{
			if  ( ( ( bsn - g_wASL32StartPSN ) % 32 ) == 15  ||  ( ( bsn -  g_wASL32Sta

rtPSN ) % 32 == 16 ) ) )
			return TRUE;
		}
 		
	 else
		if ( ( bsn % 16 ) == 7 || ( bsn % 16 ) == 8 )
			return TRUE; 
	return FALSE;
	通过这个例子,我觉得在代码审查时应该留意在判断条件较多的情况下,每个输入是否都

能正确输出,在单元测试、集成测试、系统测试时要针对边界值设计相应的测试用例。


	判断条件较多时开发人员也应该适当分开写,既使代码更易读,又不容易出错。

8、条件分支处理是否有遗漏
【案例1.8.1】
【现  象】
        在接入网主机程序的代码审查中,发现dbquery.c的DBQ_Init_ANType函数中如下

代码段缺少应有的条件分支,在数据异常的情况下,会产生较严重的问题。

【处理过程】
         该错误比较隐蔽,现在说明如下:
         Max2B1QStatTime 最大统计时间
         Max2B1QStatPortNum最大统计端口数
         MAX_2B1Q_STAT_PSN       最大统计内存分配数量 
        其中:Max2B1QStatTime(最大统计时间)和Max2B1QStatPortNum
(最大统计 端口数)的乘积不能大于MAX_2B1Q_STAT_PSN

         程序如下:
          //查询数据库,获得Max2B1QStatTime的值
	directQueryCond.tupleNo = 10;
	error_code = DB_Query( RID_OTHERS_PARA_INFO, 1,
						   (LPDBCondition)&directQueryCond,
						   (BYTE FAR *)&tempstruct0 );
	//查询数据库成功
	if( error_code == DB_SUCCESS )
	{
		//tempstruct0.data是数据库中为Max2B1QStatTime配置的值
		if ( tempstruct0.data > MAX_2B1Q_STAT_PSN )
			Max2B1QStatTime = MAX_2B1Q_STAT_PSN;
		else if ( tempstruct0.data != 0 )
			Max2B1QStatTime = tempstruct0.data;
	}

          //查询数据库,获得Max2B1QStatPortNum的值
	directQueryCond.tupleNo = 11;
	error_code = DB_Query( RID_OTHERS_PARA_INFO, 1,
						   (LPDBCondition)&directQueryCond,
						   (BYTE FAR *)&tempstruct0 );
	//查询数据库成功
	if( error_code == DB_SUCCESS )
	{

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -