gpt4 book ai didi

c++ - 位字段和值初始化导致缓冲区溢出 - 编译器错误或未定义的行为?

转载 作者:行者123 更新时间:2023-12-02 04:26:50 26 4
gpt4 key购买 nike

所以,当我尝试使用位字段来减小结构体的大小时,我在工作中遇到了一个奇怪的错误。我设法隔离了问题并生成了复制该问题的最小版本。这还有一个额外的好处,MSVC 现在甚至会警告它将要执行的操作: Link to Compiler Explorer 。不过,Clang 和 GCC 对此代码没有任何问题。

#include <new>

enum foo : unsigned char { zero, one };

struct S
{
int a{ 42 }; //Intentionally not trivial
foo b : 1;
foo c : 1;
};

auto test()
{
constexpr auto size = sizeof (S);
constexpr auto alignment = alignof(S);

struct {
alignas(alignment) unsigned char bytes[size];
} data;

//Buffer overrun on this line
::new(static_cast<void*>(&data)) S{};

//Just to avoid optimizing away the offending instructions
return data;
}

我使用的缓冲区应该适合存储对象,因为它模仿 std::aligned_storage,我正在调用 True Placement New 将我的对象存储在其中。我相信这就是 f.ex std::vector 的工作原理。尽管如此,我还是收到了这个警告:

warning C4789: buffer 'data' of size 8 bytes will be overrun; 5 bytes will be written starting at offset 4

奇怪的是,如果将大括号替换为括号(但仍应进行值初始化,对吧?)或完全删除(默认初始化),问题就会消失。

如果S很简单,问题也会消失。此外,该问题仅在启用优化的情况下发生(因此获得了有趣的调试体验)。

我不相信我在这里调用了未定义的行为,但另一种选择是 VS 2017 和 2019 中存在错误。目前我正在解决这个问题,只是不使用支撑初始化并在我怀疑的地方使用括号可能是问题,但这感觉不对。

为什么会发生这种情况?我该如何避免担心代码中存在定时炸弹?切换到另一个编译器不是一个选择。

更新:因此,进一步查看程序集,我发现在使用括号触发值初始化时,它仍然生成可疑代码。只有默认初始化才会产生预期程序集。看起来很奇怪,我肯定怀疑编译器错误,但我希望对此有更多的输入。

最佳答案

这个编译器错误是 being fixed in VS 2019 16.5 .

作为无法升级的解决方法,请考虑用常规括号替换大括号,例如将 S{...}; 替换为 S(...); 。如果没有向构造函数提供参数,请考虑简单地删除大括号,因为对象仍然以这种方式默认构造。

关于c++ - 位字段和值初始化导致缓冲区溢出 - 编译器错误或未定义的行为?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58023369/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com