【发布时间】:2020-12-29 05:08:21
【问题描述】:
我在一些计算带有整数操作数的浮点表达式的代码中遇到了 HardFault 异常。 操作数通过地址传递,然后转换(隐式或显式转换)为浮点数。 当操作数不是 32 位对齐时(不在我的控制范围内),我得到了异常。
我尝试在 Godbolt here 上重现该行为,生成的代码与我在设备上得到的一致。
基本上如下反汇编代码
vldr.32 s0, [r0] @ int
在需要对齐地址的vldr指令中直接使用传递给函数的可能未对齐的地址。
我发现this question 解决了类似的问题,但他们在那里谈论浮点指针。在那种情况下,我知道浮动不能不对齐。
在我的例子中,我处理的是允许不对齐的整数,但是编译器假定它仍然可以使用 vldr 指令中的地址。更让我疑惑的是这段代码
uint32_t pippo = *(uint32_t *)src;
float pippof = pippo * 10.0f;
在提供未对齐地址时可能会或可能不会产生异常,具体取决于优化级别,因为例如在堆栈上分配了一个整数 -O0。
所以我的问题是:
- 对于编译器(或后端,也许)来说这是正确的行为吗?由于整数可以不对齐,我希望生成的代码从 CPU 寄存器传递。
- 什么是避免此类问题的正确策略,即使通过临时 int 变量也不安全?
【问题讨论】:
-
如果 src 被定义为 32 位变量类型以外的东西,那么当然这可能会出错,这并不奇怪,这不是正确/安全的方式来获取例如字节数组和把它们变成一个词。
-
如果您要求编译器做一些可以/将在特定目标上产生错误的事情,那么是的,它可以/将产生错误,而不是编译器问题。
-
策略是编写更安全的代码。
标签: c assembly gcc arm memory-alignment