STD ::可选和包装结构成员的GCC问题
我需要使用包装的结构来解析传入数据。我还有一个 std ::可选的值,我想分配一个结构成员的值。但是,它失败了。我认为我理解问题,基本上是对与内存宽度不符的变量的引用可能是一件坏事。
代码示例用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 fails
val = (decltype(t.b)) t.b;
}
clang: https://godbolt.org/z/ewfaqb3a3a3
///godbolt.org/z/or1w5mbdg“ rel =” nofollow noreferrer“> https://godbolt.org/z/or1w5mbdg
我知道一般问题带有包装结构。由于我的目标是具有X86-64的嵌入式设备,并且正在解析的数据来自工业标准总线,因此我相信我可以安全。
I need to use a packed struct for parsing incoming data. I also have an std::optional value that I want to assign the value of one of the struct members. However, it fails. I think I understand the problem, basically making a reference to a variable that is not aligned with the memory width can be a bad thing.
The code example compiles with Clang 14, but not with GCC 12. Is it a bug or a "feature"?
#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 fails
val = (decltype(t.b)) t.b;
}
Clang: https://godbolt.org/z/eWfaqb3a3
GCC: https://godbolt.org/z/or1W5MbdG
I know of the general problems with packed structs. As my target is an embedded device with a x86-64 and the data being parsed comes from an industrial standard bus, I believe I'm safe from that.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
这是Clang和GCC如何假设ARM CPU配置的问题。
ARM CPU有一些说明是否会使用较慢的访问方法透明地使用较慢的访问方法来处理不重对的访问或通过CPU处理处理器。 clang默认为CPU,允许在GCC默认到CPU捕获非对齐的访问时允许不一致的访问。
因此,对于clang,为不规略的
tb
创建一个int&amp;
是完全可以的,因为CPU将处理可能透明的未对准访问。另一方面,对于GCC,从
tb
风险代码访问它并引起陷阱的风险代码创建int&amp;
。使用int&amp;
的功能合同说int
必须对齐。因此,编译器失败了,因为合同无法满足。但是,如果您编写
(decltype(tb))tb;
您创建了要使用tb
的副本,然后避免了不一致的问题,因为编译器知道如何复制不和谐的问题uint32_t
。您可以指定编译器标志以更改有关未对准访问的默认假设。允许GCC允许它进行编译,但假设您的ARM CPU将被配置为允许所述不一致的访问。
This is a problem of how Clang and GCC assume the ARM CPU is configured.
ARM CPUs have a bit that says whether unaligned access should cause a processor trap or be handled by the CPU using slower access methods transparently. Clang defaults to the CPU allowing unaligned access while GCC defaults to the CPU trapping unaligned access.
So for Clang, it is perfectly fine to create a
int&
for the unalignedt.b
, because the CPU will handle the unaligned access that might cause transparently.For GCC on the other hand, creating an
int&
fromt.b
risk code accessing it and causing a trap. The contract for functions taking anint&
says theint
must be aligned. So the compiler fails because the contract can't be satisfied.But if you write
(decltype(t.b)) t.b;
you create a copy oft.b
to be used which then avoids the unaligned problem because the compiler knows how to copy an unaligneduint32_t
.You can specify compiler flags to change the default assumption about unaligned access. Allowing it for GCC should make the code compile, but it assumes your ARM CPU will be configure to allow said unaligned access.