最近,在我的嵌入式软件中,我面临着一个 - 对我来说 - 奇怪的行为。
我得到了什么:运行一个 32 位 AVR32 控制器,从外部 SDRAM 启动程序,因为文件太大而无法直接从微控制器闪存启动。由于物理内存映射,内存区域分为:
堆栈(从 0x1000 开始,长度为 0xF000)(<0x1000 受 MPU 保护)
EBI SDRAM(从 0xD0000000 开始,长度为 0x00400000)。
会发生什么:不幸的是,我遇到了一个无法重现的异常。查看我给定的堆栈跟踪,会发生以下不规则事件:
名称:总线错误数据获取 - 事件源:数据总线 - 存储的返回地址:第一个未完成的指令
此外,堆栈指针具有有效值,而发生异常的地址(获取指令的最后入口点)指向内存必杀技(例如 0x496e6372,大约 0x5...、0x6...)。我想,这必须是手册所说的“第一个未完成的指令”。但是,我的源代码中的行始终是相同的:通过指针从数据数组访问成员函数。
if(mSomeArray[i])
{
mSomeArray[i]->someFunction(); <-- Crash
}
事情是:添加或删除其他源代码会使事件消失并再次返回。
我的想法:有些东西正在破坏我的记忆(映射)。这可能会出现哪些错误?
- 缓冲区溢出?
- SDRAM 控制器可能被关闭,所以它会丢失一些数据。这不是不可能,而是不太可能
- 堆栈足够大,我已经用水印检查过
- 数据总线速率和 AVR 时钟设置正确
如何解决这个问题:更多断言?不幸的是,我无法使用 AVRStudio 进行调试。任何人的提示或想法?还是我错过了一些明显的东西?
编辑:
用户提到的方法:
- 检查函数指针和数组条目的地址
- 堆栈数组的覆盖
- 未正确写入中断
- 未初始化的指针
i
通过在崩溃情况下检查阵列访问- 使用异常处理程序地址进行非法内存访问
- 使用
snprintf
而不是sprintf