Keil使用malloc异常进入hardfault调试故障手记
来源:互联网 发布:2017淘宝摇一摇在哪里 编辑:程序博客网 时间:2024/05/17 21:45
最近在做PID控温的应用,使用了自己写的菜单项目和位置式PID的相关扩展算法。效果还算满意。前几天调试程序的时候就发现在菜单定义页面的CPP文件内增加全局变量时,程序在第二级菜单项目选中时会进入hardfault,开始很纳闷,跟踪发现是malloc直接进入异常处理。想了个变通的方法来解决了问题。那就是把全局变量想办法放到函数里,变成局部变量调用,效果上确实不进hardfault了,标记了下这个错误,后面就开始做其他模块了。今天又开始在菜单项目下新增动态菜单页面,结果万幸,又进hardfault了。跟了一下C代码,还是在malloc执行过程中进入异常。下面就是详细的查错过程。
首先在hardfault上打断点,如期进入hardfault后,在keil的“call stack + locals”中观察进入异常之前的状态,如下图所示:
在进入hf之前程序运行的地址为0x8009438。在Disassembly窗口中找到相应地址的代码如下:
此时代码执行于malloc函数中的LDR指令上。指令的含义是将地址(r5+4)的内容赋给r2。为了明白LDR指令发生了什么异常,我在malloc函数的0x800941c地址打断点,并且跟踪运行结果。发现在0x8009424地址上,r5被赋值为0x270016b8,如图:
现在问题比较明朗了,因为在0x8009438处使用了(r5+4)间接寻址,而在0x8009424处,r5被赋值为0x270016b8,此值已经超出了正常内存空间范围,所以进入异常也是理所当然。
接下来继续跟踪r5寄存器的值,在0x8009420地址,执行了一个跳转,单步跟踪到跳转的位置,如图
r0被赋值为0x20001660,根据上面跟踪的结果,会有LDR r5,[r0,#0x00],那么,r5出错的根源就在于r0地址中的内容有问题。而r0的地址就是我们跟踪到的0x20001660。
在本案例的RAM配置中,0x20000000 - 0x200016c0之间是全局变量,0x200016c0 - 0x200036c0之间是heap,0x200036c0 - 0x20003ec0之间是stack。
所以被篡改的内存空间属于全局变量范围,我们为了跟踪方便,在keil中找到malloc之前的代码设置断点,单步跟踪,并且监视0x20001660内存单元的数据变化,如图:
在执行到图标绘制函数的时候,0x20001660单元出错了。此时程序在向显示缓冲写入图标数据。找到缓冲地址,发现显示缓冲和0x20001660地址单元是相邻的,到这里,可以初步猜想是绘制图标的时候内存操作越界了。检查内存位图,发现图片取模的时候是按照理想大小8*52像素去计算的,但是实际软件会以液晶驱动最小单元8bits为单位出模。所以实际大小是8*56像素。将绘制函数中的长宽重新设置后,故障解除。
从进入hardfault到内存越界,其实是很平常的问题,不过开始进到hardfault的时候很难想象问题是这样的连锁反应。开始在菜单文件中添加全局变量会让编译器重新分配空闲ram空间。如果运气好,显存和0x20001660地址之间相差大于4.那么就不会进异常。所以问题也变得离奇了一些。
此文乃本人原创,供大家学习参考。
- Keil使用malloc异常进入hardfault调试故障手记
- keil MDK hardfault调试步骤
- keil debug时直接进入HardFault
- STM32 malloc HardFault
- STM32103VE HardFault 故障问题
- Keil:调试无法进入main
- HardFault 异常定位
- keil malloc
- Keil中使用MicroLib,以及malloc
- 使用Keil进行在线调试
- Keil一进入调试器就退出的解决方法
- Keil MDK 使用malloc()&free(),stm32简单测试可用。
- malloc()函数在keil中使用应注意什么
- Keil Arm中使用malloc函数的方法
- LPC1788 HardFault异常的解决一例
- 调试STM32遇到Hardfault知识总结
- 使用keil调试查看寄存器方法
- 使用keil调试stm32时不能run
- Android中自定义属性(attrs.xml,TypedArray的使用)
- 设计模式:5 依赖倒转原则
- 60.电话 信息 邮件 评分 打开其他应用
- 用WinHex找回丢失的分区
- 设计模式:6 装饰模式
- Keil使用malloc异常进入hardfault调试故障手记
- 作为码农 ,我们为什么要写作
- 求gcd(a,b) = ax + by中的gcd(a, b)、a、b(扩展欧几里得算法尾递归版)
- 搜索引擎知识图谱相关结构化数据挖掘与去歧处理
- 设计模式:7 代理模式
- 王昊奋:大规模知识图谱技术
- 知识图谱相关会议之观后感分享与学习总结
- 【解惑】一文告诉你,该学R还是Python!
- [UVA 1629]Cake slicing[记忆化搜索]