对缓冲区使用正确的对齐方式,该缓冲区应该容纳C++中的结构
Use the right alignment for a buffer which is supposed to hold a struct in C++
假设我们有一些结构,比如
struct S
{
double a, b;
~S(); // S doesn't have to be POD
};
这样的结构通常应该具有8的对齐方式,因为它包含的最大类型的大小是8。
现在假设我们想要声明一个占位符结构来保存S
:的值
struct Placeholder
{
char bytes[ sizeof( S ) ];
};
现在我们想把它放在另一个类中:
class User
{
char someChar;
Placeholder holder;
public:
// Don't mind that this is hacky -- this just shows a possible use but
// that's not the point of the question
User() { new ( holder.bytes ) S; }
~User() { ( ( S * )( holder.bytes ) )->~S(); }
};
问题是,Placeholder
现在在User
中未正确对齐。由于编译器知道Placeholder
是由字符组成的,而不是双字符,因此它通常会使用1的对齐方式。
有没有一种方法可以用与C++03中S
的对齐方式匹配的对齐方式来声明Placeholder
?请注意,S
不是POD类型。我也知道C++11有alignas
,但这还不是普遍可用的,所以如果可能的话,我宁愿不指望它。
更新:只是澄清一下,这应该适用于任何S
——我们不知道它包含什么。
如果可以使S
符合成为union
*成员的要求,则可以使用union
。
union
保证为其最大成员提供足够的存储空间,并为其最合理的成员进行对齐。因此,如果我们将占位符设为原始字符缓冲区和实际存储在那里的所有类型的并集,那么您将拥有足够的大小和正确的对齐方式。
除了存储器本身,我们永远不会访问union
的成员。它们仅用于对齐。
大致如下:
struct Placeholder
{
union
{
char bytes [sizeof(S)];
double alignDouble;
};
};
- "作为联合成员的要求":
union
的成员不能具有:非平凡构造函数、非平凡复制构造函数、非琐碎析构函数、非平凡副本赋值运算符
我相信boost::aligned_storage
可能正是您想要的。它使用并集技巧的方式是,你的类型无关紧要(你只需要使用sizeof(YourType)
来告诉它如何对齐),以确保对齐正确。
相关文章:
- C++字符*缓冲区的大小
- 为什么msgrcv()将垃圾字符馈送到缓冲区
- 使用动态分配的数组会导致代码分析发出虚假的C6386缓冲区溢出警告
- ostream过载时的缓冲区冲洗
- C++中的高效循环缓冲区,它将被传递给C样式数组函数参数
- Xaudio2在更改缓冲区或循环时弹出声音
- 为什么我在leetcode上收到AddressSanitizer:地址0x602000000058上的堆缓冲区溢出错误
- 如何将图像传输到c++(dll)中的缓冲区,然后在c#的缓冲区中读/写
- 如何在cpp.中使用协议缓冲区存储大缓冲区/数组(char/int)
- 多线程双缓冲区
- Android P-9.0.0_r53 Logcat主缓冲区超出定义大小
- 套接字读取后,我在缓冲区中看到意外输入
- std::带有自定义缓冲区的 iostream 不允许我写入
- 从返回的顶点缓冲区查询顶点结构
- Vulkan 中的动态顶点缓冲区格式设置
- OpenGL 16 位模板缓冲区?
- 在 leetcode 上提交解决方案时出现堆栈缓冲区溢出错误
- 在 openGL 中多次绑定缓冲区
- struct.error:解压缩 C++ 结构时,解包需要 288 字节的缓冲区
- 为什么缓冲区的内容在读取空 rdbuf 时被删除?