std::optional 和打包结构成员的 gcc 问题

gcc problem with std::optional and packed struct member

提问人:nikolaj 提问时间:6/24/2022 更新时间:6/24/2022 访问量:257

问:

我需要使用打包的结构来解析传入的数据。我还有一个 std::optional 值,我想为其中一个结构成员分配值。但是,它失败了。我想我理解这个问题,基本上引用与内存宽度不一致的变量可能是一件坏事。

该代码示例使用 clang 14 编译,但不使用 gcc 12 编译。是错误还是“功能”?

#include <cstdint>
#include <optional>

struct Data {
    uint8_t a{};
    uint32_t b{};
} __attribute__((packed));

int main() {
    Data t;
    std::optional<uint32_t> val{};
    val = t.b;  // <<< this failes
    val = (decltype(t.b)) t.b;
}

叮当声:https://godbolt.org/z/eWfaqb3a3

海湾合作委员会:https://godbolt.org/z/or1W5MbdG

我知道打包结构的一般问题。由于我的目标是具有 x86-64 的嵌入式设备,并且正在解析的数据来自工业标准总线,因此我相信我是安全的。

C++ GCC clang std 选项类型

评论

0赞 KamilCuk 6/24/2022
I need to你为什么需要?只需从传入数据中提取字节并移动到适当的位置即可。没有必要使用数据包结构,你选择使用它,我说根本不使用它,要可移植并自己编写代码。
0赞 nikolaj 6/24/2022
如果我使用汇编程序,那将是一个不错的选择。当使用一种理解数据类型的语言时,我会使用它,而不是手动尝试维护一个列表,如果偏移到数据图像中。这种方法既低效又难以维护,但是的,它是可移植的,如果这是优先事项的话。

答:

3赞 Goswin von Brederlow 6/24/2022 #1

这是 clang 和 gcc 如何假设配置了 ARM cpu 的问题。

ARM CPU 有一点说明未对齐的访问是否应导致处理器陷阱,或者由 cpu 使用较慢的访问方法透明地处理。Clang 默认为 CPU 允许未对齐的访问,而 gcc 默认为 CPU 捕获未对齐的访问。

因此,对于 clang 来说,为未对齐创建 a 是完全可以的,因为 CPU 将处理可能导致的未对齐访问。int&t.b

另一方面,对于 gcc,创建一个 from risk 代码,访问它并造成陷阱。职能的合同规定必须保持一致。所以编译器失败是因为无法满足约定。int&t.bint&int

但是,如果您编写,则会创建一个要使用的副本,这样可以避免未对齐的问题,因为编译器知道如何复制未对齐的 .(decltype(t.b)) t.b;t.buint32_t

您可以指定编译器标志来更改有关未对齐访问的默认假设。允许 gcc 使用它应该使代码编译,但假设您的 ARM cpu 将配置为允许上述未对齐的访问。

评论

0赞 nikolaj 6/24/2022
好答案。谢谢,这是有道理的。我一直在寻找你提到的这些编译器标志。据我了解,我所读到的那些,它们改变了整个程序对齐数据的方式。是否可以对程序使用“正常”对齐,然后只允许对这些打包结构进行未对齐的访问?
0赞 Goswin von Brederlow 6/24/2022
不确定您阅读了什么,但 -munaligned-access 只会更改用于未对齐访问的操作码。它不会更改编译器将使用的任何对齐方式或填充。对齐访问速度仍然更快,并且是首选。
0赞 nikolaj 6/24/2022
这也仅适用于 ARM 版本。我将通过演员表接受解决方法。再次感谢您的快速回复。
0赞 Goswin von Brederlow 6/24/2022
@nikolaj 是的,如果x86_64也给出错误,也许无济于事。GCC 可能只是对制作未对齐的指针很挑剔,即使硬件没有问题。