请教C语言字节对齐问题(float数据非4字节对齐进入HardDefault)

2019-12-20 21:46发布

1》事情缘由:今天遇到一个bug,调试了大半天,最终锁定是字节对齐问题,但具体细节尚不清楚,请路过的大神帮忙指教,谢谢。
2》开发环境:stm32f103vct6 + Keil MDK - 5.23 + 未开启优化。
3》详细细节:本来程序是可以通过运行的,”手抽“将数组调动位置(由于调动位置,导致数组buf[]的起始地址开始满足4字节对齐,后来仅仅满足2字节对齐)。于是开启漫长的debug。。。
4》实际代码:删除部分无关代码,浓缩如下:
5》运行效果:如果注释掉aaa[]数组,程序正常执行;如果不注释掉aaa[]数组(注意:此时buf[]起始地址不满足4字节对齐),程序执行到下述位置,直接进入HardDefualt!!!
  1. uint8_t aaa[21];
  2. uint16_t buf[1000];
  3.                                
  4. #define data1                 (*((float *)((uint16_t *)(buf + 600))))
  5. #define data2                 (*((float *)((uint16_t *)(buf + 602))))
  6.        
  7. #define temp1                 (*((float *)((uint16_t *)addr + 0)))
  8. #define temp2                 (*((float *)((uint16_t *)addr + 2)))
  9.        
  10. #define ADDR_BASE        ((void *)((uint16_t *)buf + 600))
  11.        
  12. float func(void *addr)
  13. {
  14.         volatile float tmp;
  15.         tmp = temp1 + temp2; //程序执行到这里,直接进入HardDefault!!!
  16.         return tmp;
  17. }

  18. int main()
  19. {       
  20.         volatile float tmp;
  21.        
  22.         data1 = 1.1;
  23.         data2 = 3.3;
  24.        
  25.         board_init();
  26.        
  27.         tmp = func(ADDR_BASE);
  28.        
  29.         printf("buf = %u, tmp = %f ", (uint32_t)((void *)buf), tmp);
  30.        
  31.         while (1);
  32. }
复制代码
6》个人理解1:buf[]数组是uint16类型,因此系统默认会让buf[]数组满足2字节对齐,是否满足4字节对齐则是随机的。
7》个人理解2:由于Cortex-M3/M4默认是支持非对齐访问的(无外乎是多浪费几条指令,将非对齐最终转换为对齐访问),所以不明白此段代码为什么会进入HardDefualt,恳请指教,感谢!!!
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
该问题目前已经被作者或者管理员关闭, 无法添加新回复
22条回答
wye11083
1楼-- · 2019-12-21 00:23
 精彩回答 2  元偷偷看……
talkingbeast
2楼-- · 2019-12-21 03:45
  试试强制字节对其
擦鞋匠
3楼-- · 2019-12-21 06:13
统一回复下,我知道如何对齐,但我不知道为什么一定要4字节对齐。
路过的大神,还请帮忙指教,谢谢哈。
laoshuhunya
4楼-- · 2019-12-21 09:41
擦鞋匠 发表于 2018-3-8 20:21
统一回复下,我知道如何对齐,但我不知道为什么一定要4字节对齐。
路过的大神,还请帮忙指教,谢谢哈。 ...

因为你用了浮点数据
     
laoshuhunya
5楼-- · 2019-12-21 10:27
7》个人理解2:由于Cortex-M3/M4默认是支持非对齐访问的(无外乎是多浪费几条指令,将非对齐最终转换为对齐访问),所以不明白此段代码为什么会进入HardDefualt,恳请指教,感谢!!!
   
1、除了“直接操作指针”和“在C 程序中嵌入汇编”这两种常见情况外,一般来说编译器不会产生非对齐数据。你不仅在程序中直接操作指针,而且还很随意的使用强制类型转换,这是一种高危行为
2、不是所有指令都支持非对齐数据传输,多加载或存储指令LDM/STM还有栈操作指令都不支持非对齐传输。对于数组或结构体,编译器很多时候会产生LDM/STM指令,如果这时遇到非对齐数据就会触发“非对齐使用异常”,而非对齐使用异常默认是关闭的,这会进一步触发HardFault。
3、错误发生时,你可以查看UFSR状态寄存器(地址0xE000ED2A),确认是否发生了数据未对齐访问错误。
4、C 程序中的怪异现象不外乎以下几个原因:

C 程序中的怪异现象.png (117.22 KB, 下载次数: 1)

下载附件

C 程序中的怪异现象

2018-3-8 21:33 上传


   
7nian
6楼-- · 2019-12-21 13:51
 精彩回答 2  元偷偷看……

一周热门 更多>