您的位置:控制工程论坛网论坛 » 软件与程序 » 软件编程经典培训实例 3、变量类型定义错误

xilinxue

xilinxue   |   当前状态:在线

总积分:16186  2024年可用积分:0

注册时间: 2008-06-26

最后登录时间: 2020-03-22

空间 发短消息加为好友

软件编程经典培训实例 3、变量类型定义错误

xilinxue  发表于 2008/11/6 12:52:01      1415 查看 2 回复  [上一主题]  [下一主题]

手机阅读

 案例 1
        在FRI板上建几条FRPVC,其DLCI类型分别为:10Bit/2bytes、10bit/3bytes、16bit/3bytes、17bit/4bytes、23bit/4bytes。相应的DLCI值为:16、234、991、126975、1234567,然后保存,重起MUX,观察PVC的恢复情况,结果DLCI值为16、234和991的PVC正确恢复,而DLCI=126975的PVC恢复的数据错误为61439,而DLCI=1234567的PVC完全没有恢复。
        对于17/4类型,DLCI=126975的PVC在恢复时变成61439,根据这条线索,查找原因,发现126975-61439=65535,转化二进制就是10000000000000000,也就是说在数据恢复或保存时把原数据的第一个1给忽略了。此时第一个想法是:在程序处理中,把无符号长整型变量当作短整型变量处理了,为了证实这个判断,针对17bit/4bytes类型又重新设计测试用例:(1) 先建PVC,DLCI=65535,然后保存,重起MUX,观察PVC的恢复情况,发现PVC能够正确恢复;
(2)再建PVC,DLCI=65536,然后保存,重起MUX,观察PVC的恢复情况,此时PVC不能正确恢复。
至此基本可以断定原因就是出在这里。带着这个目的查看原代码,发现在以下代码中有问题:
int _GetFrDlci( DWORD* dwDlci, char* str, DWORD dwDlciType, DWORD dwPortType, DWORD dwSlotID, DWORD dwPortID)
{          DWORD  tempDlci;
 char szArg[80];
1 char szLine[80];
 ID LowPVCEP;
            DWORD dwDlciVal[5][2] =
     { {16,1007}, {16,1007}, {1024,64511},
       {2048,129023}, {131072,4194303} } ;
            ...
}

typedef struct tagFrPppIntIWF
{
 ...
 WORD wHdlcPort;
 WORD wHdlcDlci;     
 WORD wPeerHdlcDlci;  
 WORD wPeerOldAtmPort;
 ... 
} SFrPppIntIWFData;

DWORD  SaveFrNetIntIWFData ( DWORD *pdwWritePoint )
{
 BYTE bSlotID, bPeerSlotID;
 DWORD dwCCID, dwPeerCCID;
 WORD wHdlcPort, wAtmPort, wIci, wPeerIci, wPeerHdlcPort ;
 WORD wCount;
            ...
}

DWORD  SaveFrNetExtIWFData ( DWORD *pdwWritePoint )
{
 BYTE bSlotID;
 DWORD dwCCID, dwPeerCCID;
 WORD wHdlcPort, wAtmPort, wIci ;
 WORD wCount;
 ...
unSevData.FrNetExtIWF[wCount].bSlotID = bSlotID;
 unSevData.FrNetExtIWF[wCount].wHdlcPort = wHdlcPort;
 unSevData.FrNetExtIWF[wCount].wHdlcDlci = gFrPVCEP[bSlotID ][ gFrPVCC[bSlotID][dwCCID].dwLoPVCEP ].dwDLCI;
 unSevData.FrNetExtIWF[wCount].wOldAtmPort = wAtmPort;
 unSevData.FrNetExtIWF[wCount].wAtmDlci = gFrPVCEP[ bSlotID ][ gFrPVCC[bSlotID][dwCCID].dwHiPVCEP ].dwDLCI;
 unSevData.FrNetExtIWF[wCount].dwMapMode = gFrPVCC[bSlotID][dwCCID].dwMapMode;
     ...
       }


DWORD RestoreFrNetExtIWFData ( WORD wSlotID, BYTE *pReadPoint )
{
 WORD wCount, wTotalNetIWF;
 BYTE bSlotID, bHdlcDlciType, bAtmDlciType;
 WORD wOldAtmPort, wAtmDlci, wHdlcPort, wHdlcDlci; 
 DWORD dwMapMode, dwCIR, dwBe;
 DWORD dwCCID, dwResult, dwAtmPort;
 wTotalNetIWF = g_MuxData.SevDataSize.wFrNetExtIWFNum;
 ...
}

DWORD RestoreFrHdlcIntIWFData ( WORD wSlotID, BYTE *pReadPoint )
{
 WORD wCount, wTotalHdlcIWF;
 DWORD dwCCID, dwPeerCCID, dwAtmPort, dwPeerAtmPort;
 DWORD dwResult;
 BYTE bSlotID, bPeerSlotID;
 WORD wHdlcPort, wOldAtmPort, wCIR;
 WORD wPeerHdlcPort, wPeerOldAtmPort;
            ...
}

        其中涉及DLCI值的变量都为WORD(即无符号短整型)类型,在程序的处理时,出现WORD和DWORD(无符号长整型)类型在一句中同时存在的情况,至此可以判断问题出在这里。由于DLCI值在不同类型时的取值范围不同,前三种类型的取值范围为16~991,第四种取值范围为2048~126975,第五种取值范围为131072~4194303,所以当采用前三种DLCI类型时,采用WORD类型最大值为65535,已经完全够用了;而对于第四种类型时,其取值在超过65535时,获取DLCI值的函数_GetFrDlci()采用DWORD类型,而负责保存和恢复的两个函数SaveFrNetExtIWFData()和RestoreFrNetExtIWFData(),都把DLCI的值当作WORD类型进行处理,因此导致DLCI取值越界,于是程序把原本为长整型的DLCI强制转换成整型,从而导致DLCI值在恢复时,比原数据小65536。而在程序运行过程中,这些数据保存在DRAM中,程序运行直接从DRAM中获取数据,程序不会出错;当FRI板复位或插拔后,需要从FLASH中读取数据,此时恢复函数的错误就表现出来。
       另一个问题是为什么23/4类型的DLCI数据不能恢复?这是由于对于23/4类型的PVC,其DLCI的取值范围为:131072~4194303,而程序强制转换并恢复的数据最大只能是65535,所以这条PVC不能恢复。
        至此,DLCI数据恢复出错的原因完全找到,解决的方法是将DLCI的类型改为DWORD类型。从这个案例可以看出,在程序开发中一个很低级的错误,将在实际工作中造成很严重的后果。

 

1楼 0 0 回复
  • xilinxue

    xilinxue   |   当前状态:在线

    总积分:16186  2024年可用积分:0

    注册时间: 2008-06-26

    最后登录时间: 2020-03-22

    空间 发短消息加为好友

    xilinxue   发表于 2008/11/6 12:51:37

           在FRI板上建几条FRPVC,其DLCI类型分别为:10Bit/2bytes、10bit/3bytes、16bit/3bytes、17bit/4bytes、23bit/4bytes。相应的DLCI值为:16、234、991、126975、1234567,然后保存,重起MUX,观察PVC的恢复情况,结果DLCI值为16、234和991的PVC正确恢复,而DLCI=126975的PVC恢复的数据错误为61439,而DLCI=1234567的PVC完全没有恢复。
            对于17/4类型,DLCI=126975的PVC在恢复时变成61439,根据这条线索,查找原因,发现126975-61439=65535,转化二进制就是10000000000000000,也就是说在数据恢复或保存时把原数据的第一个1给忽略了。此时第一个想法是:在程序处理中,把无符号长整型变量当作短整型变量处理了,为了证实这个判断,针对17bit/4bytes类型又重新设计测试用例:(1) 先建PVC,DLCI=65535,然后保存,重起MUX,观察PVC的恢复情况,发现PVC能够正确恢复;
    (2)再建PVC,DLCI=65536,然后保存,重起MUX,观察PVC的恢复情况,此时PVC不能正确恢复。
    至此基本可以断定原因就是出在这里。带着这个目的查看原代码,发现在以下代码中有问题:
    int _GetFrDlci( DWORD* dwDlci, char* str, DWORD dwDlciType, DWORD dwPortType, DWORD dwSlotID, DWORD dwPortID)
    {          DWORD  tempDlci;
     char szArg[80];
     char szLine[80];
     ID LowPVCEP;
                DWORD dwDlciVal[5][2] =
         { {16,1007}, {16,1007}, {1024,64511},
           {2048,129023}, {131072,4194303} } ;
                ...
    }


    typedef struct tagFrPppIntIWF
    {
     ...
     WORD wHdlcPort;
     WORD wHdlcDlci;     
     WORD wPeerHdlcDlci;  
     WORD wPeerOldAtmPort;
     ... 
    } SFrPppIntIWFData;


    DWORD  SaveFrNetIntIWFData ( DWORD *pdwWritePoint )
    {
     BYTE bSlotID, bPeerSlotID;
     DWORD dwCCID, dwPeerCCID;
     WORD wHdlcPort, wAtmPort, wIci, wPeerIci, wPeerHdlcPort ;
     WORD wCount;
                ...
    }


    DWORD  SaveFrNetExtIWFData ( DWORD *pdwWritePoint )
    {
     BYTE bSlotID;
     DWORD dwCCID, dwPeerCCID;
     WORD wHdlcPort, wAtmPort, wIci ;
     WORD wCount;
     ...
    unSevData.FrNetExtIWF[wCount].bSlotID = bSlotID;
     unSevData.FrNetExtIWF[wCount].wHdlcPort = wHdlcPort;
     unSevData.FrNetExtIWF[wCount].wHdlcDlci = gFrPVCEP[bSlotID ][ gFrPVCC[bSlotID][dwCCID].dwLoPVCEP ].dwDLCI;
     unSevData.FrNetExtIWF[wCount].wOldAtmPort = wAtmPort;
     unSevData.FrNetExtIWF[wCount].wAtmDlci = gFrPVCEP[ bSlotID ][ gFrPVCC[bSlotID][dwCCID].dwHiPVCEP ].dwDLCI;
     unSevData.FrNetExtIWF[wCount].dwMapMode = gFrPVCC[bSlotID][dwCCID].dwMapMode;
         ...
           }



    DWORD RestoreFrNetExtIWFData ( WORD wSlotID, BYTE *pReadPoint )
    {
     WORD wCount, wTotalNetIWF;
     BYTE bSlotID, bHdlcDlciType, bAtmDlciType;
     WORD wOldAtmPort, wAtmDlci, wHdlcPort, wHdlcDlci; 
     DWORD dwMapMode, dwCIR, dwBe;
     DWORD dwCCID, dwResult, dwAtmPort;
     wTotalNetIWF = g_MuxData.SevDataSize.wFrNetExtIWFNum;
     ...
    }


    DWORD RestoreFrHdlcIntIWFData ( WORD wSlotID, BYTE *pReadPoint )
    {
     WORD wCount, wTotalHdlcIWF;
     DWORD dwCCID, dwPeerCCID, dwAtmPort, dwPeerAtmPort;
     DWORD dwResult;
     BYTE bSlotID, bPeerSlotID;
     WORD wHdlcPort, wOldAtmPort, wCIR;
     WORD wPeerHdlcPort, wPeerOldAtmPort;
                ...

    2楼 回复本楼

    引用 xilinxue 2008/11/6 12:51:37 发表于2楼的内容

  • xilinxue

    xilinxue   |   当前状态:在线

    总积分:16186  2024年可用积分:0

    注册时间: 2008-06-26

    最后登录时间: 2020-03-22

    空间 发短消息加为好友

    xilinxue   发表于 2008/11/6 12:52:01


            其中涉及DLCI值的变量都为WORD(即无符号短整型)类型,在程序的处理时,出现WORD和DWORD(无符号长整型)类型在一句中同时存在的情况,至此可以判断问题出在这里。由于DLCI值在不同类型时的取值范围不同,前三种类型的取值范围为16~991,第四种取值范围为2048~126975,第五种取值范围为131072~4194303,所以当采用前三种DLCI类型时,采用WORD类型最大值为65535,已经完全够用了;而对于第四种类型时,其取值在超过65535时,获取DLCI值的函数_GetFrDlci()采用DWORD类型,而负责保存和恢复的两个函数SaveFrNetExtIWFData()和RestoreFrNetExtIWFData(),都把DLCI的值当作WORD类型进行处理,因此导致DLCI取值越界,于是程序把原本为长整型的DLCI强制转换成整型,从而导致DLCI值在恢复时,比原数据小65536。而在程序运行过程中,这些数据保存在DRAM中,程序运行直接从DRAM中获取数据,程序不会出错;当FRI板复位或插拔后,需要从FLASH中读取数据,此时恢复函数的错误就表现出来。
           另一个问题是为什么23/4类型的DLCI数据不能恢复?这是由于对于23/4类型的PVC,其DLCI的取值范围为:131072~4194303,而程序强制转换并恢复的数据最大只能是65535,所以这条PVC不能恢复。
            至此,DLCI数据恢复出错的原因完全找到,解决的方法是将DLCI的类型改为DWORD类型。从这个案例可以看出,在程序开发中一个很低级的错误,将在实际工作中造成很严重的后果。
    3楼 回复本楼

    引用 xilinxue 2008/11/6 12:52:01 发表于3楼的内容

总共 , 当前 /