版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)
文檔簡介
1、軟件編程規(guī)范培訓(xùn)實例與練習(xí) 問題分類1 邏輯類問題(A類)指設(shè)計、編碼中出現(xiàn)的計算正確性和一致性、程序邏輯控制等方面出現(xiàn)的問題,在系統(tǒng)中起關(guān)鍵作用,將導(dǎo)致軟件死機、功能正常實現(xiàn)等嚴重問題; 接口類問題(B類)指設(shè)計、編碼中出現(xiàn)的函數(shù)和環(huán)境、其他函數(shù)、全局/局部變量或數(shù)據(jù)變量之間的數(shù)據(jù)/控制傳輸不匹配的問題,在系統(tǒng)中起重要作用,將導(dǎo)致模塊間配合失效等嚴重問題; 維護類問題(C類)指設(shè)計、編碼中出現(xiàn)的對軟件系統(tǒng)的維護方便程度造成影響的問題,在系統(tǒng)中不起關(guān)鍵作用,但對系統(tǒng)后期維護造成不便或?qū)е戮S護費用上升; 可測試性問題(D類)指設(shè)計、編碼中因考慮不周而導(dǎo)致后期系統(tǒng)可測試性差的問題。 處罰辦法 問題
2、發(fā)生率: P=D/S D=DA+0.5DB+0.25DC 其中: P 問題發(fā)生率 D 1個季度內(nèi)錯誤總數(shù) DA 1個季度內(nèi)A類錯誤總數(shù) DB 1個季度內(nèi)B類錯誤總數(shù) DC 1個季度內(nèi)C類錯誤總數(shù) S 1個季度內(nèi)收到問題報告單總數(shù) 1)當D3時,如果P3,將進行警告處理,并予以公告; 2)當D5時,如果P5,將進行罰款處理,并予以公告。目 錄一、邏輯類代碼問題第5頁1、變量/指針在使用前就必須初始化第5頁【案例1.1.1】第5頁2、防止指針/數(shù)組操作越界第5頁【案例1.2.1】第5頁【案例1.2.2】第6頁【案例1.2.3】第7頁【案例1.2.4】第8頁3、避免指針的非法引用第9頁【案例1.3.
3、1】第9頁4、變量類型定義錯誤第10頁【案例1.4.1】第10頁5、正確使用邏輯與&、屏蔽&操作符第17頁【案例1.5.1】第17頁6、注意數(shù)據(jù)類型的匹配第18頁【案例1.6.1】第18頁【案例1.6.2】第18頁7、用于控制條件轉(zhuǎn)移的表達式及取值范圍是否書寫正確第20頁【案例1.7.1】第20頁【案例1.7.2】第21頁【案例1.7.3】第22頁8、條件分支處理是否有遺漏第24頁【案例1.8.1】第24頁9、引用已釋放的資源第26頁【案例1.9.1】第26頁10、分配資源是否已正確釋放第28頁【案例1.10.1】第28頁【案例1.10.2】第29頁【案例1.10.3】第30頁【案例1.10.
4、4】第32頁【案例1.10.5】第33頁【案例1.10.6】第35頁【案例1.10.7】第38頁11、防止資源的重復(fù)釋放第39頁【案例1.11.1】第39頁12、公共資源的互斥性和競用性第40頁【案例1.12.1】第40頁【案例1.12.2】第40頁二、接口類代碼問題第43頁1、對函數(shù)參數(shù)進行有效性檢查第43頁【案例2.1.1】第43頁【案例2.1.2】第43頁【案例2.1.3】第44頁【案例2.1.4】第46頁【案例2.1.5】第47頁【案例2.1.6】第48頁2、注意多出口函數(shù)的處理第49頁【案例2.2.1】第49頁三、維護類代碼問題第51頁1、 統(tǒng)一枚舉類型的使用第51頁【案例3.1.1
5、】第51頁2、 注釋量至少占代碼總量的20第51頁【案例3.2.1】對XXX產(chǎn)品BAM某版本部分代碼注釋量的統(tǒng)計第51頁四、產(chǎn)品兼容性問題第52頁1、系統(tǒng)配置、命令方式第52頁【案例4.1.1】第52頁【案例4.1.2】第53頁2、設(shè)備對接第54頁【案例4.2.1】第54頁3、其他第55頁【案例4.3.1】第55頁五、版本控制問題第58頁1、新老代碼中同一全局變量不一致第58頁【案例5.1.1】第58頁六、可測試性代碼問題第59頁1、調(diào)試信息/打印信息的正確性第59頁【案例6.1.1】第59頁一、邏輯類代碼問題1、變量/指針在使用前就必須初始化【案例1.1.1】C語言中最大的特色就是指針。指針
6、的使用具有很強的技巧性和靈活性,但同時也帶來了很大的危險性。在XXX的代碼中有如下一端對指針的靈活使用:. . _UC *puc_card_config_tab; . . Get_Config_Table( AMP_CPM_CARD_CONFIG_TABLE, &ul_card_config_num, &puc_card_config_tab, use_which_data_area );. . b_middle_data_ok = generate_trans_middle_data_from_original_data( puc_card_config_tab, Ul_card_confi
7、g_num). .其中紅色部分巧妙的利用指向指針的指針為指針puc_card_config_tab賦值,而在蘭色部分使用該指針。但在Get_Config_Table函數(shù)中有可能失敗返回而不給該指針賦值。因此,以后使用的可能是一個非法指針。指針的使用是非常靈活的,同時也存在危險性,必須小心使用。指針使用的危險性舉世共知。在新的編程思想中,指針基本上被禁止使用(JAVA中就是這樣),至少也是被限制使用。而在我們交換機的程序中大量使用指針,并且有增無減。2、防止指針/數(shù)組操作越界【案例1.2.1】 在香港項目測試中,發(fā)現(xiàn)ISDN話機撥新業(yè)務(wù)號碼時,若一位一位的撥至18位,不會有問題。但若先撥完號碼再
8、成組發(fā)送,會導(dǎo)致MPU死機。 處理過程: 查錯過程很簡單,按呼叫處理的過程檢查代碼,發(fā)現(xiàn)某一處的判斷有誤,本應(yīng)為小于18的判斷,寫成了小于等于18。 結(jié) 論: 代碼編寫有誤。思考與啟示:1、極限測試必須注意,測試前應(yīng)對某項設(shè)計的極限做好充分測試規(guī)劃。 2、測試極限時還要注意多種業(yè)務(wù)接入點,本例為ISDN。對于交換機來說,任何一種業(yè)務(wù)都要分別在模擬話機、ISDN話機、V5話機、多種形式的話務(wù)臺上做測試。對于中繼的業(yè)務(wù),則要充分考慮各種信令:TUP、ISUP、PRA、NO1、V5等等?!景咐?.2.2】對某交換類進行計費測試,字冠011對應(yīng)1號路由、1號子路由,有4個中繼群11,12,13,14(
9、都屬于1#模塊),前后兩個群分別構(gòu)成自環(huán)。其中11,13群向為出中繼,12,14群向為入中繼,對這四個群分別進行計費設(shè)置,對出入中繼都計費。電話撥打兩次,使四個群都有機會被計費,取話單后瀏覽話單發(fā)現(xiàn)對11群計費計次表話單出中繼群號不正確,其它群的計次表中出中繼群號正常。處理過程:與開發(fā)人員在測試組環(huán)境多次重復(fù)以上步驟,發(fā)現(xiàn)11群的計次表話單有時正常,有時其出中繼群號就為一個隨機值,發(fā)生異常的頻率比較高。為什么其它群的話單正常,唯獨11群不正常呢?11群是四個群中最小的群,其中繼計次表位于緩沖區(qū)的首位,打完電話后查詢內(nèi)存發(fā)現(xiàn)出中繼群號在內(nèi)存中是正確的,取完話單后再查就不正確了。結(jié) 論:話單池的一
10、個備份指針Pool_head_1和中繼計次表的頭指針重合,影響到第一個中繼計次表的計費。思考與啟示:隨機值的背后往往隱藏著指針問題,兩塊內(nèi)存緩沖區(qū)的交界處比較容易出現(xiàn)問題,在編程時是應(yīng)該注意的地方?!景咐?.2.3】【正 文】 在接入網(wǎng)產(chǎn)品A測試中,在內(nèi)存數(shù)據(jù)庫正常的情況下的各種數(shù)據(jù)庫方面的操作都是正常的。為了進行數(shù)據(jù)庫異常測試,于是將數(shù)據(jù)庫內(nèi)容人為地破壞了。發(fā)現(xiàn)在對數(shù)據(jù)庫進行比較操作時,出現(xiàn)程序跑死了現(xiàn)象。經(jīng)過跟蹤調(diào)試發(fā)現(xiàn)問題出現(xiàn)在如下一段代碼中: 1for(i=0; idbf_count; i+)23 pDBFat = (_NM_DBFAT_STRUC *)(NVDB_BASE + DBF
11、AT_OFFSET + i*DBFAT_LEN);4if(fat_check(pDBFat) != 0) 56 pSysHead-system_flag = 0;7 head_sum();8 continue;9 10 if(strlen(dbf-dbf_name) != 0 & strncmp(dbf-dbf_name, pDBFat-dbf_name, strlen(dbf-dbf_name) = 0)11 12 dbf_ptr1 = (_UC *)pDBFat-dbf_head;13 filesize = pDBFat-dbf_fsize;14 break;15 16 在測試時發(fā)現(xiàn)程序死
12、在循環(huán)之中,得到的錯誤記錄是Bus Error(總線出錯),由此可以說明出現(xiàn)了內(nèi)存操作異常。經(jīng)過跟蹤變量值發(fā)現(xiàn)循環(huán)變量i的閥值pSysHead-dbf_count的數(shù)值為0xFFFFFFFF,該值是從被破壞的內(nèi)存數(shù)據(jù)庫中獲取的,正常情況下該值小于127。而pDBFat是數(shù)據(jù)庫的起始地址,如果pSysHead-dbf_count值異常過大,將導(dǎo)致pDBFat值超過最大內(nèi)存地址值,隨后進行的內(nèi)存操作將導(dǎo)致內(nèi)存操作越界錯誤,因而在測試過程中數(shù)據(jù)庫破壞后就出現(xiàn)了主機死機的現(xiàn)象。上面的問題解決起來很容易,只需在第一行代碼中增加一個判斷條件即可,如下:for(i=0; idbf_coun & i bySp
13、cState )語句時,主機復(fù)位。但是該語句似乎并無不妥。再分析整個函數(shù),pSpcCB在函數(shù)前部分已經(jīng)被賦值,pSpcCB = SpcCB + (PortTable+index)-spcNo;但由于得到 index 后,沒有任何判斷,導(dǎo)致若MNT/MLT端口沒有做半永久,端口激活后,執(zhí)行此部分函數(shù),(PortTable+index)-spcNo 有可能為NULL_WORD,于是,運算后,pSpcCB 可能為非法值。此時主機在取進行判斷,就不知會導(dǎo)致什么后果了。其實,改起來很簡單,只要在這兩句前增加一個判斷就行了。于是,修改代碼為:if ( (PortTable+index)-spcNo !=
14、NULL_WORD)pSpcCB = SpcCB + (PortTable+index)-spcNo;if ( SPC_STATE_OK = pSpcCB-bySpcState )。修改后,問題不再重現(xiàn)。經(jīng)過分析可以發(fā)現(xiàn),編譯環(huán)境是有很大的容許空間的,若主機沒有做充分的保護,很可能會有極嚴重的隨即故障出現(xiàn)。所以編程時一定要考慮各種可能情況;而測試中遇到此類死機問題,則要耐心的定位到具體是執(zhí)行哪句代碼時出現(xiàn)的,再進行分析。因為問題很隱蔽,直接分析海一樣的代碼是很難發(fā)現(xiàn)的。4、變量類型定義錯誤【案例1.4.1】【正 文】 在FRI板上建幾條FRPVC,其DLCI類型分別為:10Bit/2bytes
15、、10bit/3bytes、16bit/3bytes、17bit/4bytes、23bit/4bytes。相應(yīng)的DLCI值為:16、234、991、,然后保存,重起MUX,觀察PVC的恢復(fù)情況,結(jié)果DLCI值為16、234和991的PVC正確恢復(fù),而DLCI=的PVC恢復(fù)的數(shù)據(jù)錯誤為61439,而DLCI=的PVC完全沒有恢復(fù)。 對于17/4類型,DLCI=的PVC在恢復(fù)時變成61439,根據(jù)這條線索,查找原因,發(fā)現(xiàn)-61439=65535,轉(zhuǎn)化二進制就是,也就是說在數(shù)據(jù)恢復(fù)或保存時把原數(shù)據(jù)的第一個1給忽略了。此時第一個想法是:在程序處理中,把無符號長整型變量當作短整型變量處理了,為了證實這個
16、判斷,針對17bit/4bytes類型又重新設(shè)計測試用例:(1) 先建PVC,DLCI=65535,然后保存,重起MUX,觀察PVC的恢復(fù)情況,發(fā)現(xiàn)PVC能夠正確恢復(fù);(2)再建PVC,DLCI=65536,然后保存,重起MUX,觀察PVC的恢復(fù)情況,此時PVC不能正確恢復(fù)。至此基本可以斷定原因就是出在這里。帶著這個目的查看原代碼,發(fā)現(xiàn)在以下代碼中有問題:int_GetFrDlci( DWORD* dwDlci, char* str, DWORD dwDlciType, DWORD dwPortType, DWORD dwSlotID, DWORD dwPortID) DWORD tempDl
17、ci;charszArg80;1charszLine80;IDLowPVCEP; DWORDdwDlciVal52 = 16,1007, 16,1007, 1024,64511, 2048, , ; typedef struct tagFrPppIntIWFWORDwHdlcPort;WORDwHdlcDlci; WORDwPeerHdlcDlci; WORDwPeerOldAtmPort;SFrPppIntIWFData;DWORD SaveFrNetIntIWFData ( DWORD *pdwWritePoint )BYTEbSlotID, bPeerSlotID;DWORDdwCCID
18、, dwPeerCCID;WORDwHdlcPort, wAtmPort, wIci, wPeerIci, wPeerHdlcPort ;WORDwCount; DWORD SaveFrNetExtIWFData ( DWORD *pdwWritePoint )BYTEbSlotID;DWORDdwCCID, dwPeerCCID;WORDwHdlcPort, wAtmPort, wIci ;WORDwCount;unSevData.FrNetExtIWFwCount.bSlotID= bSlotID;unSevData.FrNetExtIWFwCount.wHdlcPort= wHdlcPo
19、rt;unSevData.FrNetExtIWFwCount.wHdlcDlci= gFrPVCEPbSlotID gFrPVCCbSlotIDdwCCID.dwLoPVCEP .dwDLCI;unSevData.FrNetExtIWFwCount.wOldAtmPort= wAtmPort;unSevData.FrNetExtIWFwCount.wAtmDlci= gFrPVCEP bSlotID gFrPVCCbSlotIDdwCCID.dwHiPVCEP .dwDLCI;unSevData.FrNetExtIWFwCount.dwMapMode = gFrPVCCbSlotIDdwCCI
20、D.dwMapMode; DWORD RestoreFrNetExtIWFData ( WORD wSlotID, BYTE *pReadPoint )WORDwCount, wTotalNetIWF;BYTEbSlotID, bHdlcDlciType, bAtmDlciType;WORDwOldAtmPort, wAtmDlci, wHdlcPort, wHdlcDlci; DWORDdwMapMode, dwCIR, dwBe;DWORDdwCCID, dwResult, dwAtmPort;wTotalNetIWF = g_MuxData.SevDataSize.wFrNetExtIW
21、FNum;DWORD RestoreFrHdlcIntIWFData ( WORD wSlotID, BYTE *pReadPoint )WORDwCount, wTotalHdlcIWF;DWORDdwCCID, dwPeerCCID, dwAtmPort, dwPeerAtmPort;DWORDdwResult;BYTEbSlotID, bPeerSlotID;WORDwHdlcPort, wOldAtmPort, wCIR;WORDwPeerHdlcPort, wPeerOldAtmPort; 其中涉及DLCI值的變量都為WORD(即無符號短整型)類型,在程序的處理時,出現(xiàn)WORD和DW
22、ORD(無符號長整型)類型在一句中同時存在的情況,至此可以判斷問題出在這里。由于DLCI值在不同類型時的取值范圍不同,前三種類型的取值范圍為16991,第四種取值范圍為2048,第五種取值范圍為,所以當采用前三種DLCI類型時,采用WORD類型最大值為65535,已經(jīng)完全夠用了;而對于第四種類型時,其取值在超過65535時,獲取DLCI值的函數(shù)_GetFrDlci()采用DWORD類型,而負責保存和恢復(fù)的兩個函數(shù)SaveFrNetExtIWFData()和RestoreFrNetExtIWFData(),都把DLCI的值當作WORD類型進行處理,因此導(dǎo)致DLCI取值越界,于是程序把原本為長整型
23、的DLCI強制轉(zhuǎn)換成整型,從而導(dǎo)致DLCI值在恢復(fù)時,比原數(shù)據(jù)小65536。而在程序運行過程中,這些數(shù)據(jù)保存在DRAM中,程序運行直接從DRAM中獲取數(shù)據(jù),程序不會出錯;當FRI板復(fù)位或插拔后,需要從FLASH中讀取數(shù)據(jù),此時恢復(fù)函數(shù)的錯誤就表現(xiàn)出來。 另一個問題是為什么23/4類型的DLCI數(shù)據(jù)不能恢復(fù)?這是由于對于23/4類型的PVC,其DLCI的取值范圍為:,而程序強制轉(zhuǎn)換并恢復(fù)的數(shù)據(jù)最大只能是65535,所以這條PVC不能恢復(fù)。 至此,DLCI數(shù)據(jù)恢復(fù)出錯的原因完全找到,解決的方法是將DLCI的類型改為DWORD類型。從這個案例可以看出,在程序開發(fā)中一個很低級的錯誤,將在實際工作中造成
24、很嚴重的后果?!景咐?.4.2】【正 文】 在FRI板上建幾條FRPVC,其DLCI類型分別為:10Bit/2bytes、10bit/3bytes、16bit/3bytes、17bit/4bytes、23bit/4bytes。相應(yīng)的DLCI值為:16、234、991、,然后保存,重起MUX,觀察PVC的恢復(fù)情況,結(jié)果DLCI值為16、234和991的PVC正確恢復(fù),而DLCI=的PVC恢復(fù)的數(shù)據(jù)錯誤為61439,而DLCI=的PVC完全沒有恢復(fù)。 對于17/4類型,DLCI=的PVC在恢復(fù)時變成61439,根據(jù)這條線索,查找原因,發(fā)現(xiàn)-61439=65535,轉(zhuǎn)化二進制就是,也就是說在數(shù)據(jù)恢復(fù)
25、或保存時把原數(shù)據(jù)的第一個1給忽略了。此時第一個想法是:在程序處理中,把無符號長整型變量當作短整型變量處理了,為了證實這個判斷,針對17bit/4bytes類型又重新設(shè)計測試用例:(1) 先建PVC,DLCI=65535,然后保存,重起MUX,觀察PVC的恢復(fù)情況,發(fā)現(xiàn)PVC能夠正確恢復(fù);(2)再建PVC,DLCI=65536,然后保存,重起MUX,觀察PVC的恢復(fù)情況,此時PVC不能正確恢復(fù)。至此基本可以斷定原因就是出在這里。帶著這個目的查看原代碼,發(fā)現(xiàn)在以下代碼中有問題:int_GetFrDlci( DWORD* dwDlci, char* str, DWORD dwDlciType, DW
26、ORD dwPortType, DWORD dwSlotID, DWORD dwPortID) DWORD tempDlci;charszArg80;charszLine80;IDLowPVCEP; DWORDdwDlciVal52 = 16,1007, 16,1007, 1024,64511, 2048, , ; typedef struct tagFrPppIntIWFWORDwHdlcPort;WORDwHdlcDlci; WORDwPeerHdlcDlci; WORDwPeerOldAtmPort;SFrPppIntIWFData;DWORD SaveFrNetIntIWFData (
27、 DWORD *pdwWritePoint )BYTEbSlotID, bPeerSlotID;DWORDdwCCID, dwPeerCCID;WORDwHdlcPort, wAtmPort, wIci, wPeerIci, wPeerHdlcPort ;WORDwCount; DWORD SaveFrNetExtIWFData ( DWORD *pdwWritePoint )BYTEbSlotID;DWORDdwCCID, dwPeerCCID;WORDwHdlcPort, wAtmPort, wIci ;WORDwCount;unSevData.FrNetExtIWFwCount.bSlo
28、tID= bSlotID;unSevData.FrNetExtIWFwCount.wHdlcPort= wHdlcPort;unSevData.FrNetExtIWFwCount.wHdlcDlci= gFrPVCEPbSlotID gFrPVCCbSlotIDdwCCID.dwLoPVCEP .dwDLCI;unSevData.FrNetExtIWFwCount.wOldAtmPort= wAtmPort;unSevData.FrNetExtIWFwCount.wAtmDlci= gFrPVCEP bSlotID gFrPVCCbSlotIDdwCCID.dwHiPVCEP .dwDLCI;
29、unSevData.FrNetExtIWFwCount.dwMapMode = gFrPVCCbSlotIDdwCCID.dwMapMode; DWORD RestoreFrNetExtIWFData ( WORD wSlotID, BYTE *pReadPoint )WORDwCount, wTotalNetIWF;BYTEbSlotID, bHdlcDlciType, bAtmDlciType;WORDwOldAtmPort, wAtmDlci, wHdlcPort, wHdlcDlci; DWORDdwMapMode, dwCIR, dwBe;DWORDdwCCID, dwResult,
30、 dwAtmPort;wTotalNetIWF = g_MuxData.SevDataSize.wFrNetExtIWFNum;DWORD RestoreFrHdlcIntIWFData ( WORD wSlotID, BYTE *pReadPoint )WORDwCount, wTotalHdlcIWF;DWORDdwCCID, dwPeerCCID, dwAtmPort, dwPeerAtmPort;DWORDdwResult;BYTEbSlotID, bPeerSlotID;WORDwHdlcPort, wOldAtmPort, wCIR;WORDwPeerHdlcPort, wPeer
31、OldAtmPort; 其中涉及DLCI值的變量都為WORD(即無符號短整型)類型,在程序的處理時,出現(xiàn)WORD和DWORD(無符號長整型)類型在一句中同時存在的情況,至此可以判斷問題出在這里。由于DLCI值在不同類型時的取值范圍不同,前三種類型的取值范圍為16991,第四種取值范圍為2048,第五種取值范圍為,所以當采用前三種DLCI類型時,采用WORD類型最大值為65535,已經(jīng)完全夠用了;而對于第四種類型時,其取值在超過65535時,獲取DLCI值的函數(shù)_GetFrDlci()采用DWORD類型,而負責保存和恢復(fù)的兩個函數(shù)SaveFrNetExtIWFData()和RestoreFrNe
32、tExtIWFData(),都把DLCI的值當作WORD類型進行處理,因此導(dǎo)致DLCI取值越界,于是程序把原本為長整型的DLCI強制轉(zhuǎn)換成整型,從而導(dǎo)致DLCI值在恢復(fù)時,比原數(shù)據(jù)小65536。而在程序運行過程中,這些數(shù)據(jù)保存在DRAM中,程序運行直接從DRAM中獲取數(shù)據(jù),程序不會出錯;當FRI板復(fù)位或插拔后,需要從FLASH中讀取數(shù)據(jù),此時恢復(fù)函數(shù)的錯誤就表現(xiàn)出來。 另一個問題是為什么23/4類型的DLCI數(shù)據(jù)不能恢復(fù)?這是由于對于23/4類型的PVC,其DLCI的取值范圍為:,而程序強制轉(zhuǎn)換并恢復(fù)的數(shù)據(jù)最大只能是65535,所以這條PVC不能恢復(fù)。 至此,DLCI數(shù)據(jù)恢復(fù)出錯的原因完全找到
33、,解決的方法是將DLCI的類型改為DWORD類型。從這個案例可以看出,在程序開發(fā)中一個很低級的錯誤,將在實際工作中造成很嚴重的后果。5、正確使用邏輯與&、屏蔽&操作符【案例1.5.1】【案例描述】:由于C語言中位與比求模效率高,因而系統(tǒng)設(shè)計時,對于模128的地方都改為與127,系統(tǒng)定義的宏為#define MOD128 127和#define W_MOD 127(定義的宏的名字易引起誤解),但實際程序中還是采取求模,從而引起發(fā)送窗口欲重發(fā)的和實際重發(fā)的不一致,最終導(dǎo)致鏈路復(fù)位此類嚴重問題,曾在定位此問題時花了不少時間?!咎幚磉^程】:處理過程如下:#define MOD128 127 /隊列長1
34、28,當隊頭到128時,上其返回。#define W_MOD 127 /發(fā)送窗口隊列,意義同上。在函數(shù)L2_TO_L1()中,有如下語句: linkstate_ptr-SendWin.head = (head + 1) % W_MOD ;這里當head=126時,SendWin.head = 0,這將造成發(fā)送窗口指針和隊列窗口指針錯位,造成鏈路復(fù)位;另外,在重發(fā)函數(shù)void INVOKE_RETRANSMISSION(_US logic_link,_US n_r)中,有如下語句: retran_num = (LinkStatelogic_link.Vs + MOD128 - (_UC)n_r)
35、 % MOD128 ; w_head = (LinkStatelogic_link.SendWin.head + W_MOD - retran_num) % W_MOD ;第一個語句求欲重發(fā)的消息包個數(shù),第二個語句求重發(fā)的起始位置,當Vs小于n_r時,將造成實際重發(fā)數(shù)小于欲重發(fā)數(shù),同時造成實際起始重發(fā)位置和欲重發(fā)起始位置錯開,從而引起鏈路復(fù)位。上面三個語句應(yīng)該做如下改動: linkstate_ptr-SendWin.head = (head + 1) & W_MOD ; retran_num = (LinkStatelogic_link.Vs + MOD128 + 1 - (_UC)n_r)
36、& MOD128 ; w_head = (LinkStatelogic_link.SendWin.head + W_MOD + 1 - retran_num) & W_MOD ;【結(jié) 論】:由于鏈路通信對系統(tǒng)效率要求很高,算法采用效率最高的,但位與(&)和求模(%)這小小的區(qū)別,造成的竟是鏈路復(fù)位這種嚴重的錯誤。【思考與啟示】:對這類問題,大家在閱讀代碼或代碼審查時一定要注意,仔細一點往往能發(fā)現(xiàn)問題,但在測試中來定位這種問題,花費的時間往往更長。6、注意數(shù)據(jù)類型的匹配【案例1.6.1】【案例描述】下面通過測試中的一個例子來說明這個問題:命令DSP N7C是用來顯示NO7電路狀態(tài)的,其參數(shù)設(shè)備類
37、型DID支持TUP和ISUP,參數(shù)信道號BSN支持多值輸入(最多支持32路查詢),正常情況下該命令沒有問題。但試了非正常情況下,問題就出來了。1、首先試BSN參數(shù)越界情況,即參數(shù)BSN超過32路查詢,選了幾個數(shù)據(jù)段,問題就出來了。對于0&300和0&256,該命令返回結(jié)果不一致,對前者認為參數(shù)越界,對后者返回執(zhí)行成功。2、對于參數(shù)DID,選定一種設(shè)備類型(TUP或ISUP),讓參數(shù)BSN所包含的32路電路跨越TUP和ISUP,兩次結(jié)果是不一致的?!咎幚磉^程】反饋到開發(fā)人員那里,第一個問題是BAM的問題,第二個問題是SM的問題?!窘Y(jié) 論】1、為數(shù)據(jù)超出范圍溢出造成,int值賦值給BYTE,造成數(shù)
38、據(jù)丟失。2、問題的產(chǎn)生是因為查詢的第一個信道是TUP電路,但是卻按ISUP電路查詢。ISUP的維護處理函數(shù)判斷第一個信道不是ISUP信道,認為整個的PCM不是ISUP類型的PCM,返回全部的電路狀態(tài)為未安裝。消息處理不合理。TUP也會產(chǎn)生如此錯誤。【思考與啟示】我們的MML命令并不是無懈可擊的,許多表面上的小問題,往往隱藏著代碼的缺陷和錯誤。【案例1.6.2】【正 文】當我們使用PC-LINT檢查代碼時,會發(fā)現(xiàn)大量的數(shù)據(jù)類型不匹配的告警,大部分情況下,這種代碼上存在的問題并不會引起程序功能實現(xiàn)上的錯誤,但有些情況下,也許會產(chǎn)生嚴重的問題: 一、不同數(shù)據(jù)類型變量之間賦值引起的問題,實際上,該類問
39、題也可以分為幾種情況:1、直接賦值,比如,把一個WORD型變量賦給一個INT型變量,如果WORD型變量大于32767,INT型變量得到的就是一個負值了。 【例一】一次測試過程中發(fā)現(xiàn),SDH送的告警在BAM調(diào)試窗口打印出紅色提示:File(XXX),Line(XXX):Invalid alarm id ,from: 7, AlarmId: 65463經(jīng)過檢查數(shù)據(jù)發(fā)現(xiàn),并沒有ID為65463的告警,分析上報的數(shù)據(jù)幀,發(fā)現(xiàn)上報的告警ID為B7,原來代碼中有一處強制類型轉(zhuǎn)換: sdhAlmStru.AlarmId = (WORD)RecvBufferiTmpLen + 5;char型強制轉(zhuǎn)換成WORD
40、型。B7就變成了FFB7,十進制就是65463。由于char是有符號型,B7的第8位為1,所以轉(zhuǎn)換后為FFB7,而不是代碼作者希望的00B7,如果第8位是0,或該變量是BYTE型,轉(zhuǎn)換就不會有問題了。2、函數(shù)形參和實參不一致,實際上和第一種情況本質(zhì)上是一樣的,只是表現(xiàn)的形式不太一樣,這種情況也是代碼中經(jīng)常出現(xiàn)的問題,下面例子是測試中曾經(jīng)發(fā)現(xiàn)的一個小問題:【例二】在file01中的INT DebugMsgProc(char byMsg0, char byMsg1)函數(shù),兩個形參都是char型,而實際傳入的參數(shù)都是BYTE型,結(jié)果函數(shù)中的如下語句:PrintfE(PID_RED, %d ticks
41、 time out!,byMsg1);在byMsg1大于127時,輸出錯誤的結(jié)果。 二、不同數(shù)據(jù)類型之間的比較操作在循環(huán)終止條件的判斷中,不同類型變量的比較操作是容易造成死循環(huán)錯誤的地方,同時也是開發(fā)人員容易忽視的地方,值得測試人員多加留意。下面兩個例子是該類錯誤的兩種典型情況:【例三】file02文件中某函數(shù)中如下代碼,可能造成死循環(huán): . int i;WORD *pCheck =(WORD*)p;WORD wCheckSum=*pCheck;pCheck+;for(i=1;idwLen/2;i+)wCheckSum=(*pCheck);pCheck+;/binlen had already
42、 word alignmentreturn (wCheckSum);. 該段代碼是在DOS環(huán)境下用BC編譯的,由于循環(huán)變量i是int型(2個字節(jié)),而dwLen是DWORD型(4個字節(jié)),如果dwLen大于65536,那么該函數(shù)就是死循環(huán)了。上面的例子是不同類型變量之間直接比較操作,還有一種情況是函數(shù)的返回值與另一不同類型的變量比較,見下面例子:【例四】file03.c文件中某函數(shù)中如下代碼, while( ftell(fp) Part3). ftell返回long型,而Part是DWORD型,有符號變量和無符號變量的比較,可能造成死循環(huán)。類似的例子還有很多,類型不匹配的問題還有許多種情況,都
43、是代碼中的隱患,有時會造成嚴重的后果,需要引起足夠的重視。對于該類問題,我們可以利用PC-LINT工具對代碼進行細致的檢查。7、用于控制條件轉(zhuǎn)移的表達式及取值范圍是否書寫正確【案例1.7.1】【案例描述】:在測試主機MPU板倒換功能時,如果MPU備份充分,倒換前后對處于激活狀態(tài)的電路應(yīng)無影響,即不影響通話。但近期測試發(fā)現(xiàn),如果兩局通過DT板進行一號對接,MPU備份倒換卻發(fā)生斷話。具體現(xiàn)象為:如果DT板的第1個PCM系統(tǒng)電路為故障,則MPU倒換時復(fù)位該DT板,如果DT板的第2個PCM系統(tǒng)電路為故障,則MPU倒換時復(fù)位下一塊DT。【處理過程】:據(jù)查,MPU倒換時會自動復(fù)位處于“故障”態(tài)的電路,但由
44、于計算錯誤(多加了32),錯復(fù)位了下一個PCM系統(tǒng)32路電路?!窘Y(jié) 論】:如此嚴重問題為什么到今天才發(fā)現(xiàn)?因為我們在實驗室中一般采用同一單板的2個PCM系統(tǒng)自環(huán)進行測試,則不會在某單板上有故障和空閑電路共存,自環(huán)屏蔽了錯誤?!舅伎寂c啟示】:自環(huán)是在測試環(huán)境下常用的一種提高效率的手段,但一旦條件允許,我們的測試工作應(yīng)盡量模擬網(wǎng)上的實際環(huán)境進行。【案例1.7.2】平時對計費功能進行測試的時候,瀏覽詳細話單都是比較注意話單本身的正確性,并沒有注意該命令對系統(tǒng)的影響。所以當瀏覽少量話單的時候,并沒有發(fā)現(xiàn)該命令的異常。但是當時間的跨度較大時,詳細話單數(shù)量較多,問題就出現(xiàn)了。執(zhí)行如下命令:LST AMA:
45、 TP=NRM, SD=1999&7&1, SA=YES;當瀏覽了大約10萬張詳細話單后,終端與BAM的連接關(guān)閉。重建連接后,發(fā)現(xiàn)話單臺的命令不能執(zhí)行。觀察BAM的性能,發(fā)現(xiàn)話單臺仍占有CPU50%以上的利用率,說明原來的任務(wù)仍在執(zhí)行。需要關(guān)一下話單臺才能恢復(fù)正常。重復(fù)上述步驟,當終端與BAM的連接尚未關(guān)閉時主動斷開此次連接,結(jié)果同上。反饋到開發(fā)人員那里,發(fā)現(xiàn)該現(xiàn)象與設(shè)計的初衷是相違背的。本來話單臺控制最多輸出200張話單,這是為了防止過多話單的輸出顯示會增加BAM的開銷,從而降低BAM的性能。查看一下源代碼,問題就發(fā)現(xiàn)了。話單臺控制最多輸出200張話單程序如下 while(timeCur =
46、 timeEnd) timeCur += tsOneDay;/加一天while(fileBill.Read(&rpt, sizeof(CBillReport) = sizeof(CBillReport) . /只輸出滿足條件的前200張話單 if (+wBillCount = 200) break; /一個文件查詢結(jié)束 /所有文件查詢結(jié)束在話單輸出200張之后,程序只退出一層循環(huán),仍然會從下一天話單繼續(xù)輸出,導(dǎo)致向MML發(fā)幀過多,造成MML和話單臺都被堵死。修改ProcessQueryBill()函數(shù) /只輸出滿足條件的前200張話單 if (+wBillCount = 200) timeCur = timeEnd
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
- 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 醫(yī)療設(shè)備管理人才梯隊建設(shè)
- 2026年南方醫(yī)科大學(xué)珠江醫(yī)院大數(shù)據(jù)中心招聘數(shù)據(jù)工程師備考題庫及一套答案詳解
- 2026年保山萬宇投資開發(fā)有限公司招聘備考題庫參考答案詳解
- 2026年成都市龍泉驛區(qū)東山國際小學(xué)招聘備考題庫帶答案詳解
- 2026年天柱縣總工會公開招聘專職工會社會工作者備考題庫及1套完整答案詳解
- 2026年吉林醫(yī)藥學(xué)院附屬醫(yī)院公開招聘工作人員備考題庫參考答案詳解
- 2026年大連海洋大學(xué)學(xué)報編輯部公開招聘編輯人員備考題庫附答案詳解
- 2026年中國建筑第四工程局有限公司深圳分公司招聘備考題庫及一套答案詳解
- 2026年慈溪市上林人才服務(wù)有限公司公開招聘安全生產(chǎn)服務(wù)項目派遣制輔助管理人員備考題庫有答案詳解
- 2026年中國人壽保險股份有限公司麗江分公司招聘人事助理、保單服務(wù)專員備考題庫完整答案詳解
- 中考物理 題型06【電學(xué)實驗題】押題必做15題
- 企業(yè)安全生產(chǎn)責任制評估與改進方案
- 昆侖神話敘事的百年學(xué)術(shù)史重構(gòu)與跨學(xué)科研究
- (必刷)湖南專升本《基礎(chǔ)護理學(xué)》考點精粹必做300題-含答案
- 隧道監(jiān)測與數(shù)據(jù)采集技術(shù)方案
- 總經(jīng)辦辦公室工作總結(jié)及計劃
- 圍堤水下拋石工程的施工技術(shù)方案與安全措施
- 2025-2030中國鋼結(jié)構(gòu)建筑在新能源設(shè)施建設(shè)中的應(yīng)用前景報告
- 焊工安全培訓(xùn)考試題(附答案)
- 2025年直招軍官面試題型及答案
- 人工智能AI賦能干行百業(yè)白皮書2025
評論
0/150
提交評論