[技术问答]

单片机的数组越界与溢出

[复制链接]
3242|93
手机看帖
扫描二维码
随时随地手机跟帖
belindagraham|  楼主 | 2023-7-28 10:00 | 显示全部楼层 |阅读模式

数组越界C语言数组是静态的,不能自动扩容,当下标小于零或大于等于数组长度时,就发生了越界(Out Of Bounds),访问到数组以外的内存。如果下标小于零,就会发生下限越界(Off Normal Lower);如果下标大于等于数组长度,就会发生上限越界(Off Normal Upper)。
C语言为了提高效率,保证操作的灵活性,并不会对越界行为进行检查,即使越界了,也能够正常编译,只有在运行期间才可能会发生问题。请看下面的代码:
#include <stdio.h>
int main()
{
int a[3] = {10, 20, 30}, i;
for(i=-2; i<=4; i++){
printf("a[%d]=%d\n", i, a[ i]);
}
return 0;
}
运行结果:a[-2]=-858993460a[-1]=-858993460a[0]=10a[1]=20a[2]=30a[3]=-858993460a[4]=-858993460
越界访问的数组元素的值都是不确定的,没有实际的含义,因为数组之外的内存我们并不知道是什么,可能是其它变量的值,可能是函数参数,可能是一个地址,这些都是不可控的。
由于C语言的”放任“,我们访问数组时必须非常小心,要确保不会发生越界。每个C语言程序员的生涯中都遇到过越界错误,因为越界错误有时候不容易发现,也不容易复现。
当发生数组越界时,如果我们对该内存有使用权限,那么程序将正常运行,但会出现不可控的结果(如上例所示);如果我们对该内存没有使用权限,或者该内存压根就没有被分配,那么程序将会崩溃。请看下面的例子:
#include <stdio.h>
int main()
{
int a[3];
printf("%d", a[10000]);
return 0;
}
在 VS2010 下运行,会出现运行时错误:


在 C-Free 5.0 下运行,会弹出程序停止工作的对话框:
每个程序能使用的内存都是有限的,该程序要访问 4*10000 字节处的内存,显然太远了,超出了程序的访问范围。这个地方的内存可能没有被分配,可能是系统本身占用的内存,可能是其它数据的内存,如果放任这种行为,将带来非常危险的后果,操作系统只能让程序停止运行。
数组溢出当赋予数组的元素个数超过数组长度时,就会发生溢出(Overflow)。如下所示:int a[3] = {1, 2, 3, 4, 5};数组长度为3,初始化时却赋予5个元素,超出了数组容量,所以只能保存前3个元素,后面的元素被丢弃。

一般情况下数组溢出不会有什么问题,顶多是丢失多余的元素。但是当以字符串的形式输出字符数组时,就会产生不可控的情况,请看下面的代码:
#include <stdio.h>
int main()
{
char str[10] = "88888888888888888888";
puts(str);
return 0;
}
字符串的长度大于数组长度,数组只能容纳字符串的前面一部分,也就是"http://c.b",即使编译器在最后添加了'\0',它也保存不到数组里面,所以 printf() 扫描数组时不会遇到结束符'\0',只能继续向后扫描。而后面内存中的数据我们不知道是什么,字符能否识别,何时遇到'\0',这些都是不确定的。当字符无法识别时,就会出现乱码,显示奇怪的字符。
由此可见,在用字符串给字符数组赋值时,要保证数组长度大于字符串长度,以容纳结束符'\0'。
总结:能够理解数组越界和数组溢出的原因,并且在编程中注意避免。

使用特权

评论回复
youtome| | 2023-8-4 18:48 | 显示全部楼层
数组越界怎么解决?              

使用特权

评论回复
hilahope| | 2023-8-4 20:04 | 显示全部楼层
单片机的数组越界与溢出的检测可以通过设置数组边界标志位和数组大小监测位来实现。

使用特权

评论回复
albertaabbot| | 2023-8-4 20:26 | 显示全部楼层
使用一些限制宏来限制你的上限。              

使用特权

评论回复
mickit| | 2023-8-4 20:41 | 显示全部楼层
常规的数组时无法判断数组越界的。

使用特权

评论回复
jackcat| | 2023-8-4 20:50 | 显示全部楼层
在关键代码块中插入断言语句,检查数组的索引是否满足预期的范围条件。

使用特权

评论回复
jkl21| | 2023-8-4 21:18 | 显示全部楼层
大多数现代编译器都提供了警告功能,可以检测到数组越界和溢出的潜在问题。

使用特权

评论回复
hudi008| | 2023-8-4 21:26 | 显示全部楼层
在关键位置使用断言来验证数组索引的有效性。

使用特权

评论回复
ulystronglll| | 2023-8-4 21:34 | 显示全部楼层
某些编译器或运行时库函数提供了对数组访问的边界检查功能。

使用特权

评论回复
mikewalpole| | 2023-8-4 21:57 | 显示全部楼层
在访问数组元素之前,始终检查索引是否在数组边界内。

使用特权

评论回复
louliana| | 2023-8-4 22:07 | 显示全部楼层
在代码中使用断言来验证变量和表达式的值是否在预期范围内。

使用特权

评论回复
timfordlare| | 2023-8-4 22:17 | 显示全部楼层
数组大小监测位可以用来监测数组的使用情况,当数组溢出时,监测位会发出报警信号,从而可以检测出溢出情况。

使用特权

评论回复
yorkbarney| | 2023-8-4 22:26 | 显示全部楼层
仔细审查代码并进行全面的测试是检测数组越界和溢出的一种常用方法。

使用特权

评论回复
houjiakai| | 2023-8-5 10:15 | 显示全部楼层
边界标志位可以在数组开始和结束的位置设置,当数组访问越界时,标志位会被触发,从而可以检测出越界情况。

使用特权

评论回复
sanfuzi| | 2023-8-5 10:42 | 显示全部楼层
某些单片机或微控制器提供了硬件保护机制来检测数组越界和溢出。

使用特权

评论回复
janewood| | 2023-8-5 10:50 | 显示全部楼层
c语言是如何检测到数组越界的              

使用特权

评论回复
hudi008| | 2023-8-5 12:10 | 显示全部楼层
如果是gdb的话,定位到数组越界的前一行,然后找到可能的越界数组

使用特权

评论回复
janewood| | 2023-8-5 12:13 | 显示全部楼层
数组的下标越界可在编译哪个阶段发现?

使用特权

评论回复
maudlu| | 2023-8-5 12:38 | 显示全部楼层
使用动态分配的内存来替代固定大小的数组,可以在运行时动态调整数组的大小。

使用特权

评论回复
deliahouse887| | 2023-8-5 13:02 | 显示全部楼层
在访问数组元素时,检查索引是否在合法范围内。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

25

主题

1442

帖子

0

粉丝