一个数据类型可以跨越多个虚拟页面吗?(视窗)

逆向工程 视窗 编译器 虚拟内存
2021-07-11 16:19:46

多字节原始数据类型(即 int、double、float 等)能否在 Windows 上跨越多个虚拟页面?

ex) 虚拟页上双精度值的前 4 个字节,以及下一个虚拟页上双精度值的下一个 4 字节。这可能吗*?

结构体呢?数组?


*我认为在技术上可以将虚拟页面中任意内存的最后 4 个字节的地址转换为双指针,只要后面还有另一个虚拟页面——但我更好奇是否这样可以在编译/解释程序中自然发生。

2个回答

我不明白为什么不。

例如,如果我将一个二进制文件映射到内存中,我可以这样配置它的结构:

//Visual Studio code

#pragma pack(push,1)
struct STRUCT1{
    char dummy[0x1000 - 4];
    double fDouble;
};
#pragma pack(pop)

struct STRUCT2{
    STRUCT1 __declspec(align(0x1000)) s1;
};


int main()
{
    STRUCT2 s2 = {0};
    s2.s1.fDouble = -123.124;

    //This construct is just to give you the direct pointer
    double* pD = (double*)((BYTE*)&s2 + offsetof(STRUCT2, s1.fDouble));
    double fDVal = *pD;

}

然后,如果我们在最后一行中断调试器并检查的值pD(即RAX在此屏幕截图中的寄存器中):

在此处输入图片说明

在此处输入图片说明

您将看到该double变量跨越了页面边界(以红色标记):

在此处输入图片说明

从效率的角度来看,这远非理想(因为那些不“喜欢”的 SSE2 指令未对齐),但很有可能。

虽然它可能是手工编码的结果,但实际上不太可能是编译代码的结果。编译器通常会适当地对齐数据,这样 4 字节的值将从 4 字节对齐的地址开始,8 字节在 8 字节等处开始,以避免对齐异常。