2

如果运行时检查确认没有超过 4GB 的虚拟内存(或 RAM)可用,是否有任何平台(如果有,是哪个?)可以执行以下操作?

// 1) cast pointer to void pointer
// 2) cast void pointer to uint64 type
// 3) set most significant bytes of uint64 type to 0 (might be wrong choice)
// 4) store as uint32 type
uint32_t trimmed_pointer = (uint64_t) (void *) pointer & 0x00000000ffffffff;

并取回原始指针:

same_as_before_t *pointer = (void *) (uint64_t) trimmed_pointer

我意识到这可能是一个可怕的黑客攻击,并且完全取决于操作系统的内存管理器如何实现虚拟内存(以及编译器?),所以我纯粹出于好奇而问这个问题。

4

2 回答 2

3

为了帮助移植假定指针可以安全地存储在 32 位整数类型中的笨拙的旧 32 位程序,Windows 仍然尊重IMAGE_FILE_LARGE_ADDRESS_AWARE64 位程序的 PE 标头中的标志。

如果程序头中没有设置该标志,系统将不会为进程分配超过 2GB 的地址。

默认情况下,对于 64 位构建,链接器设置标志(即,默认情况下,64 位程序的地址空间不受限制)。如果您想指示您的 64 位程序不应获得超过 2GB 的地址空间,/largeaddressaware:no请在构建程序时将该选项传递给链接器。有关详细信息,请参阅http://msdn.microsoft.com/en-us/library/windows/desktop/aa384271.aspx

请记住,此功能旨在帮助移植不能正确处理指针的程序,而不是让您编写此类程序。还要记住一个重要的事实,即虚拟地址与物理地址几乎没有关系(换句话说,即使您的 RAM 少于 4GB,系统仍然可以使用 TB 范围内的虚拟地址)。

于 2013-06-25T07:36:00.797 回答
2

如果程序没有被标记为大地址感知(或者更确切地说,被明确标记为感知),这将在 64 位 Windows 上工作,因为它明确地是 Windows 在这种情况下所做的,只有一个警告:如果我记得正确地,指针在转换回 64 位时应该进行符号扩展。

无论如何,这并不重要,因为所有“负”指针只能由内核代码访问,并且不应在用户空间代码中可见(该/LARGEADDRESSAWARE:NO标志还保护程序免受/3GB内核开关的影响,这会使该确认为假)。

当然,只有在启动 EXE 文件时才会读取:如果 Aware EXE 加载了 non-Aware DLL,那么,砰!

于 2013-06-25T07:30:37.073 回答