gpt4 book ai didi

c++ - 编译时检查结构的 32/64 位二进制兼容性?

转载 作者:行者123 更新时间:2023-11-30 05:20:50 27 4
gpt4 key购买 nike

我正在开发一个 C++ 程序,出于充分的理由 (1),它需要一种存储在磁盘上的二进制数据格式。组成该数据是任意 struct 条目。

我的程序有 32 位和 64 位版本,二进制数据文件可能由一个写入并由另一个读取。这意味着存储结构的字段必须是具有可预测大小和对齐方式的类型,以便生成的布局对于两种自然字大小都是相同的。

我担心 future 的维护者可能会在没有真正思考的情况下添加一个 int 或像一个 uint32_t 紧跟一个 这样的东西而意外地违反这一点uint64_t.

有什么方法可以进行编译时检查(即 static_assert)结构在 32 位和 64 位上的布局相同位系统?如果前者不可能,运行时检查怎么样?

从概念上讲,我认为它会是这样的:

for (every field):
static_assert: sizeof_32(field) == sizeof_64(field)
static_assert: offset_of(next_field) == offset_of(field) + sizeof(field)

或者更简单地说:

static_assert: sizeof_32(struct) == sizeof_64(struct)

鉴于该程序正在为两种位大小进行编译,从技术上讲,仅在一种架构上断言是可以的,因为这仍然会暴露问题。

如果被检查的结构在某种程度上受到限制(例如需要显式填充字段)也可以,只要可以保证正确即可。


  1. 文件是内存映射的,所有读/写都是随机访问的通过指针。序列化不是一种选择。

最佳答案

这是我能想到的最接近“自动”的东西:

对于将在此持久性二进制数据中使用的所有结构,添加具有预期实例大小的属性。

struct MyPersistentBinaryStructure {
// Expected size for 32/64-bit check.
static constexpr size_t kExpectedInstanceSize = 80;

... 80 bytes of fixed size fields and appropriate padding ...
};

然后,在查找该二进制数据中结构地址的代码中,检查该值:

template <typename T>
T* GetAsObject(Reference ref) {
static_assert(std::is_pod<T>::value, "only simple objects");
static_assert(T::kExpectedInstanceSize == sizeof(T), "inconsistent size");
return reinterpret_cast<T*>(GetPointerFromRef(ref));
}

任何将结构编译为不同大小的构建都会产生编译时错误。这不会对构建进行 future 验证,因为对于宽度 X 不同的定义在实际构建在宽度 X 的体系结构上之前不会被捕获,但至少你会知道并且也许能够适应不破坏格式的结构(例如 32 位 int -> int32_t)。

事实证明这样做是值得的,因为它立即在代码中发现了三个 32/64 不兼容问题,我已经非常仔细地手动检查了这些问题。其中两个错误会导致数据损坏;另一个只是一些额外的尾部填充。

关于c++ - 编译时检查结构的 32/64 位二进制兼容性?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40497537/

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