一次数组越界的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 的捷径。

原文地址:https://www.cnblogs.com/qsyll0916/p/9061841.html

时间: 2024-08-28 21:42:37

一次数组越界的bug经历的相关文章

QRCode 数组越界异常

因为需求的缘故需要解析出ios二维码的地址,把解析的地址传到按钮上 把功能写好之后用几张二维码测试没问题后提交到svn上,第二天生产环境正好发版,发现有个应用的按钮点了一直没反应,看了下控制台发现报错 居然是数组越界...纠结了好久.最后点到那个二维码看看有什么特别之处 一切尽在无言中(我擦...居然是1000多像素的二维码,你逗我呢)...

谨防数组越界!

今天第一次对数组越界问题有了深切的感受,数组越界如果在Release版本中运行也不会报错,如果是Debug版本的话,若直接通过常量数值引用数组下标会被检测到数组越界,若通过变量引用数组下标也是不会被检测到的!!! 测试下面的代码, 1 #include <stdio.h> 2 3 int main(void) 4 { 5 int arr[1][1] = {20}, brr[1] = {1}, y = 5; 6 7 //printf("%d\n", arr[5][0] ==

数组越界

1. 找出下列代码的错误 void test() { char string[10]; char *str="0123456789"; strcpy(string,str); }字符串str需要11个字节才能存放下(包括末尾的'\0'),而string只有10个字节的空间:strcpy会导致数组越界. void test() { char string[10]; char str[10]; int i; for(int i=0; i<10; i++) { str[i]='a';

iOS 数组越界 Crash处理经验

我们先来看看有可能会出现的数组越界Crash的地方: - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { WelfareItem *item = [_datasourceArray objectAtIndex:indexPath.row];//有可能会越界,你在下拉刷新时会用[_datasourceArray removeAllObjects],这时你又点了某个

数组越界保护与消息传递black机制

数组越界保护if(index.row <= [array count]) 发送消息[[NSNotificationCenter defaultCenter]     postNotificationName:@"chuandi" object:self]; 接收消息 自己写个action的动作[[NSNotificationCenter defaultCenter] addObserver:self                                         

ListView 适配器实现getviewtypcount() 数组越界IndexOutOfBoundException

ListView中Item的多布局显示,需要用到了getViewTypecount和getItemViewType这两个重写方法,但是做完后出现了如下提示错误:java.lang.ArrayIndexOutOfBoundsException: (数组越界) 原因:居然是getItemViewType这里里面返回的Type必须是从0开始的,如果getviewtypecount等于2,那么getItemViewType返回的数值是从0~1的常数.简单说,在刚开始设置type常量时,是从0开始递增的,

iOS 关于数组越界的解决方法

所谓的数组越界,就是假如你的下标总数现在为32个,然后你在下一秒又执行了一个方法要从50个数据里惊醒赋值啊 筛选之类的 而你此时数量为32 50的数据还没有请求到 往往会出现数组越界的崩溃信息 大概是这样的 -[__NSArrayI objectAtIndex:]: index 100 beyond bounds [0 .. 9]'  具体的解决方式我们通常会选择把数组做个判断列如 return nil; 虽然在大多数情况下是可以的,但是多少并不严谨,如果你设置了一个事件循环执行的NStimer

从一道简单模拟题看数组越界以及其他

题目要求比较明确,可能做起来难度不是很大. 但我这道题用了比较久的时间. 原因是我用了一种特别容易错的方法.我在移动数组元素的时候采用不用辅助数组由前往后复制的方法(想来我也真是没事找事干),然后在这种方法下我起初交了许多遍WA,然后自己经过长时间的测试终于发现了问题所在,不止一个,各种逻辑错误. 总结主要有以下几点: 分类讨论不够明确,不够完整 没有考虑到前边操作对后边数据的影响 没有意识到数组越界的后果(a[-1],a[maxn]) 要发现和解决这些问题并不容易,需要有很高的调试技巧,通过这

Java中的数组越界问题

Java中数组初始化和OC其实是一样的,分为动态初始化和静态初始化, 动态初始化:指定长度,由系统给出初始化值 静态初始化:给出初始化值,由系统给出长度 在我们使用数组时最容易出现的就是数组越界问题,好了,下面来演示一下 int [][] array = {{1,2,3},{1,4}}; System.out.println(array[1][2]); 这是一个二维数组,很明显,数组越界了,控制台中会打印如下信息: p.p1 { margin: 0.0px 0.0px 0.0px 0.0px;