一次數組越界的bug經歷


數組和指針都是C里面的好東西,但是一旦使用不當,真的會讓人抓狂。

下面是寫程序時遇到的一次數組越界的經歷,感覺對以后寫程序有點啟發,所以記錄下來。

 

起因:

我想用OLED動態顯示一組浮點數,而且浮點數的長度是不定的。

1、如果只是單純的顯示,沒有消隱的話,上一次的長數的據殘留會影響下一次短長度數據的顯示。

2、如果顯示一次就清空一次顯示區域的話,數據會一直抖動,一開始以為是我刷新頻率不夠,故把刷新頻率由100HZ改為1000HZ,但是效果還是和之前一樣!

后來想想也是,不管我把刷新頻率改為多少,清空后的空白和顯示的數據都是相同的頻率。1000hz顯示數據,那么也是1000hz的空白。所以會抖動嚴重。

3、把數據的每一位都取出來單獨顯示,但是這樣就又帶來了數據對齊的問題。不爽,不好看,棄之。

4、使用sprintf格式化需要顯示的數據為字符串。然后用OLED的顯示字符串的方式顯示。

 

於是有了下面這樣的程序:

    sprintf((char *)weight_string,"%.1f",weight);        //格式化為字符串
    Clear_Left_Num(money_string);                                //消除殘余
    OLED_Show_String(42,2,weight_string);

    sprintf((char *)price_string,"%d",price);
    Clear_Left_Num(money_string);
    OLED_Show_String(42,4,price_string);

這段程序在定時器中斷函數中調用。weight 和 price 就是我想顯示的浮點數。

先格式化為字符串,然后顯示。OLED_Show_String() 的前兩個參數是字符的起始顯示坐標。

Clear_Left_Num 函數如下:

void Clear_Left_Num(unsigned char *num_string)
{
    while(*num_string != '.')
        num_string++;
    //一位小數點后面的數據用空格刷新
    *(num_string+2) = ' ';
    *(num_string+3) = ' ';
    *(num_string+4) = ' ';
}

思路就是把小數點后一位后面的殘余數據用空格刷新。

但是實驗現象是在顯示完第一行數據之后,本來應該在第二行顯示第二個數據,但是他 在第一行數據的后面又顯示了第二行的數據!!也就是說第二行數據顯示了兩次。

為什么會顯示兩次呢?我程序中就寫了一次啊、、、

 

分析:

既然是顯示的問題,那就先看看這個顯示函數!

/*----------------------------------
**函數名稱:OLED_Show_String
**功能描述:光標處顯示字符串,字符串可以用數組表示,unsigned char string_2[] = {"THIS IS A TEST  "};
**參數說明:X,Y為坐標
            * chr:字符串首地址
**作者:Andrew
**日期:2018.1.24
-----------------------------------*/
void OLED_Show_String(u8 x, u8 y, u8 *chr)
{
    u8 j=0;
    while (chr[j]!='\0')
    {
        OLED_ShowChar(x,y,chr[j]);

        x+= 8 ;

        if(x>120){x=0;y+=2;}  //自動換行寫

        j++;
    }
}

原來這個函數會在數組結束之前,顯示數組的全部內容。因為數組的最后一個結尾標志是  '\0’

那么,上面第一行一直在顯示,說明他可能沒有遇到數組結束標識符。

查看數組定義的大小:

unsigned char weight_string[7] = {0};
unsigned char price_string[3] = {0};

原來 weight_string 數組的最后一個結束標志被我賦值成了空格。那么他就會一直讀取存儲在這個數組后面的內存數據,並且給顯示出來。也就是所謂的“數組越界”。

幸好我們只是讀取顯示,並沒有改寫這個數據!

既然他顯示的是第二行的數據,說明第二行的數據就是存儲在在這個數組后面的內存中。

查看編譯器生成的map文件:

果然,第二個數組緊鄰着第一個數組存儲。

第一個數組讀取越界之后,讀到了第二個數組。

到此,問題解決。

 

總結:

一定要看到程序的內在聯系。分析內存雖然困難,但是卻是找到煩人bug 的捷徑。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM