多字节原始数据类型(即 int、double、float 等)能否在 Windows 上跨越多个虚拟页面?
ex) 虚拟页上双精度值的前 4 个字节,以及下一个虚拟页上双精度值的下一个 4 字节。这可能吗*?
结构体呢?数组?
*我认为在技术上可以将虚拟页面中任意内存的最后 4 个字节的地址转换为双指针,只要后面还有另一个虚拟页面——但我更好奇是否这样可以在编译/解释程序中自然发生。
多字节原始数据类型(即 int、double、float 等)能否在 Windows 上跨越多个虚拟页面?
ex) 虚拟页上双精度值的前 4 个字节,以及下一个虚拟页上双精度值的下一个 4 字节。这可能吗*?
结构体呢?数组?
*我认为在技术上可以将虚拟页面中任意内存的最后 4 个字节的地址转换为双指针,只要后面还有另一个虚拟页面——但我更好奇是否这样可以在编译/解释程序中自然发生。
我不明白为什么不。
例如,如果我将一个二进制文件映射到内存中,我可以这样配置它的结构:
//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 字节等处开始,以避免对齐异常。