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

Incorrect member offset calculated by compiler in constructor

本文关键字:成员 偏移量 不正确 计算 构造函数 编译器      更新时间:2023-10-16

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解析为这个+0x10。

很少观察到:

  • 将alignof(8(添加到keyVar解决了问题
  • 将构造函数的定义移动到cpp文件解决了这个问题
  • 在标头中使用初始化列表时出现相同问题
  • 无法在较新的编译器上在不同的项目中复制简化版本(正在处理(
  • 如果在定义构造函数时类中使用的每个类型都是已知的,则检查标头
  • 运行调试,关闭优化,x64,工具集:windowsapplicationfordrivers10.0,VS2017

构造函数代码似乎没有考虑keyVar对齐。是否存在一些标准/编译器限制,或者只是编译器缺陷/副作用?

通过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  

打印方式:

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  

更新

原来的项目好像出了问题。我已经将可疑的类移到了单独的项目中,使用了相同的编译工具,并且无法复制。

周一将从另一个方面开始——从最初的项目中删除一些东西,看看会有什么不同。

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