【发布时间】:2020-11-23 02:46:01
【问题描述】:
我有一些代码在过去与glm 一起工作的低级别上工作。我将 glm 的所有用法切换为 Eigen 现在我观察到一个奇怪的行为,即同一个结构似乎在代码的不同点具有不同的对齐方式。
这是 gdb 在初始化后给我的:
(gdb) p sizeof(CellShadingInfo)
$1 = 240
(gdb)
现在让我们看看具体全局结构的构造:
const std::unordered_map<std::string, size_t> uniform_size_map = {
{"GuiTransform", sizeof(GuiTransform)},
{"UniformBufferObject", sizeof(UniformBufferObject)},
{"GuiVisualProperties", sizeof(GuiVisualProperties)},
{"PostProcessingEffects", sizeof(PostProcessingEffects)},
{"LineProperties", sizeof(LineProperties)},
{"PointInfo", sizeof(PointInfo)},
{"GaussianVisualization", sizeof(GaussianVisualization)},
{"ParticleUBO", sizeof(ParticleUBO)},
{"CameraInfo", sizeof(CameraInfo)},
{"MVPOnlyUbo", sizeof(MVPOnlyUbo)},
{"WireframeDebugInfo", sizeof(WireframeDebugInfo)},
{"CellShadingInfo", sizeof(CellShadingInfo)},
{"GaussianProperties", sizeof(GaussianProperties)}
};
这是全局的,所以它的初始化代码会在 main 之前运行。但由于 LUP 已被定义为常量,因此其中的所有值都应该是最终值,从而防止意外覆盖。
但是根据gdb:
(gdb) p uniform_size_map
$2 = std::unordered_map with 13 elements = {["CellShadingInfo"] = 228, ["MVPOnlyUbo"] = 192, ["ParticleUBO"] = 16,
["GaussianVisualization"] = 48, ["PointInfo"] = 36, ["PostProcessingEffects"] = 8, ["GuiVisualProperties"] = 20,
["GaussianProperties"] = 8, ["CameraInfo"] = 12, ["UniformBufferObject"] = 192, ["WireframeDebugInfo"] = 16,
["LineProperties"] = 40, ["GuiTransform"] = 16}
所以我唯一的解释是编译器在 preinit 方法与常规运行时的编译过程中使用了不同的对齐方式。然而,这听起来很荒谬。
【问题讨论】:
-
我的猜测是,
CellShadingInfo有几个不同的定义,或者在不同的命名空间中(没关系),或者在相同的命名空间中但在不同的翻译单元中(这违反了 ODR)。也许有一些成员被包含或排除,或者基于宏改变类型;并且不同的翻译单元使用定义的不同宏进行编译。 -
整个程序中只有一个 CellShadingInfo 声明(刚刚用 grep 检查),我正在使用的宏处理器的唯一用途是通过包含。这会导致问题吗?
-
嗯,它可能类似于
struct CellShadingInfo {SomeType x;},其中SomeType的定义因翻译单元而异。或者可能有一个数组,其边界由一个变化的常数定义。违反 ODR 的方式有很多种。 -
"SomeType 的定义因翻译单元而异" 我 100% 确定这发生在 Eigen 向量中。该结构有很多,但其他一切都只是普通的整数和浮点数,所以这就是问题所在。我该如何解决?
-
找出它们最终不同的原因,确保所有翻译单元的构建配置一致。
标签: c++ struct compilation alignment padding