C++中的gcc浮点指针强制转换导致SIGBUS错误

gcc float pointer casting in C++ causing SIGBUS error

本文关键字:转换 SIGBUS 错误 gcc 中的 指针 C++      更新时间:2023-10-16

我有一个动态定义的无符号8位整数数组:

const uint8_t *data;

它包含一个字节流,并被重新解释为各种数据类型。我可以通过以下方式将此数据流中的位置n重新解释为基本类型类型

type value =  *((type*) &data[n]);

这适用于在Windows下使用Visual Studio编译器的所有数据类型,但是,当在Linux下使用gcc进行编译时,当类型为浮点值(取消引用的位置在数据数组的范围内)时,会产生SIGBUS错误。进一步的调查表明,正是指针取消引用导致了此错误。我已经通过使用memcpy解决了这个问题,但我想知道为什么这会首先导致问题,因为引用的地址是有效的。relpret_cast会更合适吗?如果是,为什么?

编辑:

我没有提到Linux系统有ARM体系结构@MSchangers在下面指出,对于不同的配置,可能有更严格的指针对齐要求。一项简短的研究表明,虽然上述内容在x86体系结构上有效(尽管C/C++标准不允许),但在ARM上未对齐的指针解引用会导致总线错误。

强制转换确实是个问题。它已经是一个reinterpret_cast,尽管您使用了旧的C语法。但是只有当&data[n]实际上是有效的float*时才允许强制转换。SIGBUS意味着它不是。该地址可能是一个有效的char*地址,但这并不意味着它是一个无效的float*地址。特别地,float*可能具有更严格的对准要求。

正如MSchanges在本线程中提到的那样,强制转换的目标类型的对齐要求比源类型的更强,这导致CPU上的SIGBUS不处理未对齐的访问。

处理该问题的方法是memcpy:

const uint8_t *data = ...;
type value;
memcpy(&value, data, sizeof value);