编译器在构造函数中计算的成员偏移量不正确

Incorrect member offset calculated by compiler in constructor

VC++ 编译器出于未知原因在构造函数中为具有以下结构的 class 生成不正确的成员偏移量:

class AlignTest
{
public:
    enum TEnum : char
    {
        one,
        two
    };
protected:
    int& ref;
    char c;
    size_t keyVar;
public:
    AlignTest(int& x. size_t other = 0) : ref(x)
    {
        c = 1;
        keyVar = other;
    }
    void Print();
};

由于未知原因,在构造函数执行期间,keyVar 赋值写入地址 this+0x09,但由于对齐,keyVar 实际上位于 this+0x10。令人惊讶的是,当 运行 Print 方法时,代码会正确生成并将 keyVar 解析为 this+0x10。

少量观察:

构造函数代码似乎没有考虑 keyVar 对齐。是否有一些 standard/compiler 限制,或者它只是编译器 bug/side 的影响?

用 VS 的一段反汇编代码更新,注意与 "this" 地址的偏移量。

在 .h 文件的构造函数中:

keyVar = other;
00007FF76C32D4DB 48 8B 44 24 08       mov         rax,qword ptr [this]  
00007FF76C32D4E0 48 8B 4C 24 18       mov         rcx,qword ptr [other]  
00007FF76C32D4E5 48 89 48 09          mov         qword ptr [rax+9],rcx  

在 Print 方法中:

size_t tmp2 = keyVar;
00007FF76C3918D0 48 8B 84 24 40 02 00 00 mov         rax,qword ptr [this]  
00007FF76C3918D8 48 8B 40 10          mov         rax,qword ptr [rax+10h]  
00007FF76C3918DC 48 89 44 24 68       mov         qword ptr [rsp+68h],rax  

更新

原来的项目好像有问题。我已将可疑 classes 移至单独的项目,使用相同的编译工具但无法重现。

周一将以另一种方式开始——从原来的项目中删除一些东西,看看会有什么不同。

正如 Igor Tandetnik 所建议的那样,问题出在带有构造函数 (1) 的编译单元和带有打印方法 (8) 的单元中的不同包级别。在项目的 header.

之一中发现未还原 pack(1) 指令