IAR 编译器中的指针
pointers in the IAR compiler
长话短说,我使用 IAR EWARM 编译器在 C 中实现了这个。
uint8_t packet[2048];
uint32_t* src = (uint32_t*)&packet[9];
uint32_t var = *src++;
最后一行导致总线故障。
uint8_t packet[2048];
uint32_t* src = (uint32_t*)&packet[9];
uint32_t var = 0xFE;
*src++;
现在没有总线故障。我可以在调试器中看到 src 指向我期望它指向的数据。增加它按预期工作,但尝试读取它会导致总线故障。
有什么帮助吗?
可能是您的 MCU 需要读取 32 位整数才能与 32 位对齐。
&packet[9]
肯定不是 32 位对齐的,这就是你出错的原因。
&packet[9]
可能未针对 uint32_t
正确对齐。在 ARM CPU 上看到 "Bus Error" 通常是对齐错误的标志。 See here 对齐的解释。
在第二个示例中,它可能通过优化 *
操作来避免总线故障,因为您从不使用结果。
请注意,即使您修复了此问题,代码仍会因违反严格的别名规则而导致未定义的行为。 (uint8_t
不能别名为 uint32_t
)。一些编译器现在可能 "work correctly" 但代码可能会在未来的任何时候中断。
您的代码的安全等价物是:
uint8_t *src = &packet[9];
uint32_t var;
memcpy(&var, src, sizeof var);
src += sizeof var;
请注意,如果源数据被指定为具有特定的整数字节顺序(例如,您是从网络流中获取它,而不是之前通过相同方法保存的数据),那么您将需要使用一种方法读取独立于 uint32_t
表示的数据。 (换句话说,"endianness")。
长话短说,我使用 IAR EWARM 编译器在 C 中实现了这个。
uint8_t packet[2048];
uint32_t* src = (uint32_t*)&packet[9];
uint32_t var = *src++;
最后一行导致总线故障。
uint8_t packet[2048];
uint32_t* src = (uint32_t*)&packet[9];
uint32_t var = 0xFE;
*src++;
现在没有总线故障。我可以在调试器中看到 src 指向我期望它指向的数据。增加它按预期工作,但尝试读取它会导致总线故障。
有什么帮助吗?
可能是您的 MCU 需要读取 32 位整数才能与 32 位对齐。
&packet[9]
肯定不是 32 位对齐的,这就是你出错的原因。
&packet[9]
可能未针对 uint32_t
正确对齐。在 ARM CPU 上看到 "Bus Error" 通常是对齐错误的标志。 See here 对齐的解释。
在第二个示例中,它可能通过优化 *
操作来避免总线故障,因为您从不使用结果。
请注意,即使您修复了此问题,代码仍会因违反严格的别名规则而导致未定义的行为。 (uint8_t
不能别名为 uint32_t
)。一些编译器现在可能 "work correctly" 但代码可能会在未来的任何时候中断。
您的代码的安全等价物是:
uint8_t *src = &packet[9];
uint32_t var;
memcpy(&var, src, sizeof var);
src += sizeof var;
请注意,如果源数据被指定为具有特定的整数字节顺序(例如,您是从网络流中获取它,而不是之前通过相同方法保存的数据),那么您将需要使用一种方法读取独立于 uint32_t
表示的数据。 (换句话说,"endianness")。