zoukankan      html  css  js  c++  java
  • 一次数组越界的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]!='')
        {
            OLED_ShowChar(x,y,chr[j]);
    
            x+= 8 ;
    
            if(x>120){x=0;y+=2;}  //自动换行写
    
            j++;
        }
    }

    原来这个函数会在数组结束之前,显示数组的全部内容。因为数组的最后一个结尾标志是  '’

    那么,上面第一行一直在显示,说明他可能没有遇到数组结束标识符。

    查看数组定义的大小:

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

    原来 weight_string 数组的最后一个结束标志被我赋值成了空格。那么他就会一直读取存储在这个数组后面的内存数据,并且给显示出来。也就是所谓的“数组越界”。

    幸好我们只是读取显示,并没有改写这个数据!

    既然他显示的是第二行的数据,说明第二行的数据就是存储在在这个数组后面的内存中。

    查看编译器生成的map文件:

    果然,第二个数组紧邻着第一个数组存储。

    第一个数组读取越界之后,读到了第二个数组。

    到此,问题解决。

    总结:

    一定要看到程序的内在联系。分析内存虽然困难,但是却是找到烦人bug 的捷径。

  • 相关阅读:
    Dockerfile文件详解
    docker-compose.yml文件
    Linux集中日志服务器rsyslog
    数据库连接池DBUtils使用
    js开关插件使用
    flask基础
    redis系列--深入哨兵集群
    Python算法基础
    redis系列--主从复制以及redis复制演进
    redis系列--redis4.0深入持久化
  • 原文地址:https://www.cnblogs.com/qsyll0916/p/9061841.html
Copyright © 2011-2022 走看看