« 上一篇下一篇 »

内存未对齐导致的hardfault分析

今天写代码时,碰到了一个问题,就是我在某个函数里面新增了一个成员变量,然后在该函数结束并返回调用函数时,进入了hardfault。然后我将该变量前面添加static修饰符,使其不再使用堆栈中分配的内存,错误就没有了。这让我感觉很不解,于是又进行了后续的验证。

初步怀疑问题原因就是内存未对齐,导致访问时出错而引起hardfault。当我将static修饰符去掉,然后对该函数内的局部变量的位置进行了一番调整,问题也没有再出现。于是我仍然使用原来出问题的那种变量定义顺序,这里面有一个二维数组,定义的形式是uint8 ch_name[][10],第一维的大小是没有显示定义的,于是我将第1维的大小给定一个固定值,再调试发现,也没有出现hardfault,这时我就想,难道是因为这个数组所占用的内存空间前后没有对齐,于是我又将第1维的固定值去掉,调整变量的定义顺序,使得在这个数组前面的内存为4字节对齐,然后再调试,发现又出现hardfault,既然这样,我就又把这个数组之后的内存调整为4字节对齐,仍然产生hardfault。很奇怪的是,此时我再将第1维的大小给定,再调试,发现仍然有问题,这就很令人费解了。虽然很大程度上我判定就是内存未对齐导致的hardfault,但是这么一测试,却发现结果表现的很奇怪。

因为时间问题,没有继续细究了,虽然没有完全确定问题原因,但是至少找到了解决办法,那就是:如果要在函数内定义局部数组变量,且数组的元素个数没有给出确定的值的话,最好在前面加上static修饰符,这样的话该数组变量使用的就不是堆栈里面的内存空间了,不管有没有对齐,都不会导致堆栈访问(比如函数返回时的出栈操作)时出现hardfault了。

总结:以后函数返回时出现hardfault,首先要考虑内存对齐,通过调整该函数内部局部变量的定义顺序来测试验证是否是内存未对齐而导致的问题。此外,不管是局部变量还是全局变量,尤其是涉及到结构体的定义的,要尽可能在定义变量时保证内存4字节对齐,以减少出错的概率


——2019.09.09 22:41   于广州花都