首页 > 解决方案 > 编译器在构造函数中计算的成员偏移量不正确

问题描述

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

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 对齐。是否有一些标准/编译器限制或者它只是编译器错误/副作用?

用 VS 用一段反汇编代码更新,注意从“这个”地址的偏移量。

在 .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  

更新

似乎原始项目有问题。我已将可疑类移至单独的项目,使用相同的编译工具并且无法重现。

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

标签: c++visual-c++visual-studio-2017

解决方案


正如 Igor Tandetnik 建议的那样,问题出在具有构造函数 (1) 的编译单元和具有打印方法 (8) 的单元中的不同包级别。在项目标头之一中发现未还原的 pack(1) 指令。


推荐阅读