MSP430数组填充越界引起的栈溢出导致程序跑飞如何解决

一、预备知识
1、栈区(stack)—由编译器自动分配释放,存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈。
2、堆区(heap)—一般由程序员分配释放,若程序员不释放,程序结束时可能由os回收。注意它与数据结构中的堆是两回事,分配方式倒是类似于链表。
(这是一个前辈写的,非常详细)
//main.cpp
inta=0;全局初始化区
char*p1;全局未初始化区
main()
{
intb;栈
chars[]=abc;栈
char*p2;栈
char*p3=123456;123456在常量区,p3在栈上。
staticintc=0;全局(静态)初始化区
p1=(char*)malloc(10);
p2=(char*)malloc(20);
分配得来得10和20字节的区域就在堆区。
strcpy(p1,123456);123456放在常量区,编译器可能会将它与p3所指向的123456优化成一个地方。
}
二、堆和栈的理论知识
2.1申请方式
stack:
由系统自动分配。例如,声明在函数中一个局部变量intb;系统自动在栈中为b开辟空间
heap:
需要程序员自己申请,并指明大小,在c中malloc函数
如p1=(char*)malloc(10);
在c++中用new运算符
如p2=(char*)malloc(10);
但是注意p1、p2本身是在栈中的。
msp430 堆栈溢出 解决
msp430程序在运行的过程中,出现死机的现象,通过iar编译器观察,死机的原因是栈溢出。
因为定义的局部变量是在栈内的,所以分析可能是局部变量导致栈溢出,最有可能导致编译器不能事先判断
使用了多少栈的(超出设定值会报警),就是程序中产生新的占用栈的变量,由之前的经验推测是数组越界,因为如果程序不顾数组的边界,越界不断的往里填东西,越界的部分就会被当成局部变量,占用栈的内存。
因为栈是从ram的底部网上长(存数据)的,而其他程序运行的数据是从顶部往下的,所以当栈越存越多,越积越高的时候,栈就会和程序运行时的数据碰头,二者占满整个ram内存,此时栈再继续消耗,栈再向上长,直接覆盖掉程序运行时所需的变量,程序就要跑飞了。
(iar430中定义的变量是从ram的起始地址向上(由小到大),而堆栈是从ram的终止地址向下(由大到小)。
以msp430f5438为例,它是16kb的ram,起始地址为0x1c00h,终止地址为005bffh(data sheet 15页),所以它的变量是从0x1c00h开始,向0x005bffh方向存放,而堆栈是从0x005bffh开始,向0x1c00h方向压栈。当变量存储空间和堆栈最大占用空间在中间相遇时,就发生了堆栈溢出。)
下面就详细介绍如何查看ram使用情况:
1当然是烧程序到目标板里呀
2选择view/memory,打开memory窗口
3从ram的起始地址0x1c00h开始,输入0x3fff(16kb),再回车
4选中0x1c00h~0x005bffh区域,右键选择memory fill……
5在memory fill中的start写入:0x1c00h,length写:0x3fff,value填入ff(也可填入其他值),被选中的区域全填充ff
6运行程序,跑一遍设计的所有功能,再停止cspy,看看memory窗口
7如果再填充的区域内已经没有ff存在,就说明已经发生堆栈溢出或是会有溢出的危险(ram刚好够用)。最好保留一定余量的ram不被改变,以防发生溢出
验证:定义一个uart0_rx_hex_buf[400];
在程序中加入这个代码。
unsigned int i;
for(i=0;i= uart0_rx_hex_maxlen)
uart0_rx_hex_len = 0;
这两句子不能去掉,因为,在没有接收到协议数据(配置数据,fe……fa)之前,uart0_rx_hex_buf和uart0_rx_buf一样在接收返回的at指令返回,数组在不断的填装,uart0_rx_buf每隔一段时间就会被读取一次,并清空,因而不会出现溢出。但是在没有收到配置数据之前,uart0_rx_hex_buf不会清空,且在配置完之后,只要服务站不发协议数据,也不会清空,因而uart0_rx_hex_buf基本处于只填装不清空的状态,最后远远越界,最终导致开头分析的结果。
加了清零语句:
if(uart0_rx_hex_len >= uart0_rx_hex_maxlen)
uart0_rx_hex_len = 0;
后,死机在12小时内在没有出现,其他比对机器全部死机,初步证明分析应该是正确的。
#pragma vector=usci_a0_vector
__interrupt void usci_a0_isr()
{
uca3txbuf=uca0rxbuf;//把接收的数据发到u3便于观察(lcx注)
//接收字符数据时
uart0_rx_buf[uart0_rx_len] = uca0rxbuf;
uart0_rx_len++;
readuart0_new=read_cycle;
//接收协议数据时(16进制)
uart0_rx_hex_buf[uart0_rx_hex_len] = uca0rxbuf;
if((uart0_rx_hex_buf[uart0_rx_hex_len]==0xff)&&(uart0_rx_hex_buf[uart0_rx_hex_len-1]==0xfe))
{
uart0_rx_hex_buf[0]=uart0_rx_hex_buf[uart0_rx_hex_len-1];
uart0_rx_hex_buf[1]=uart0_rx_hex_buf[uart0_rx_hex_len];
uart0_rx_hex_len=1;
}
else if((uart0_rx_hex_buf[uart0_rx_hex_len]==0xfa)&&(uart0_rx_hex_buf[uart0_rx_hex_len-1]==0xff))
{
readuart0_permit=1;
uca0ie &= ~ ucrxie;
}
uart0_rx_hex_len++;
if(uart0_rx_hex_len >= uart0_rx_hex_maxlen)
uart0_rx_hex_len = 0;
}

单相电表接线图
便捷好用的开发板不只有Arduino
鼠笼式电动机自耦降压启动手动控制电路
重大消息:乐视汽车已停产?10亿美金的骗局?
华为第二代Mate X折叠屏手机曝光新增了手写笔功能
MSP430数组填充越界引起的栈溢出导致程序跑飞如何解决
未来随着科技的发展,GPU能力会超越CPU吗
格罗方德携手英特尔助力Ayar Labs完成2400万美元A轮融资
家用光疗灯具研制成功,医生可进行远程监控慢性溃疡患者病症
多家上市公司宣布将分拆旗下的锂电业务板块独立IPO
交流电机的结构组成及工作原理
影响视觉成像的核心参数
华为5G网络相关消息
关于驱动程序设计的5个小技巧
步伐虽慢但坚定但从未停歇 因此未来物联网的导入只会逐步加速
苹果手机滞销,代工厂的冬天也来了
Applied的在线SEM测量系统提供3-D成像功能
中国首款肌肉外甲问世,是一种新型穿戴机器人设备
国内新建锂盐项目进展“追踪”
技术融合是发展关键,国内VR产业发展速度将加快