一次数组越界的bug经历

Posted Andrew_qian

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了一次数组越界的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 的捷径。

 

以上是关于一次数组越界的bug经历的主要内容,如果未能解决你的问题,请参考以下文章

如何测量代码片段的调用次数和经过时间

vscode代码片段建议bug

每日一练5

一例 Go 编译器代码优化 bug 定位和修复解析

需要示例代码片段帮助

小程序连续点击bug解决