以32位整数存储64位指针,提供最大虚拟存储器地址&lt; = UINT32_MAX(例如,当RAM大小<= 4GB时)

时间:2013-06-25 05:57:10

标签: c pointers 64-bit 32bit-64bit virtual-memory

是否有任何平台(如果是,哪个?)可以完成以下内容,前提是运行时检查确认虚拟内存(或RAM)不超过4GB?

// 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

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

2 个答案:

答案 0 :(得分:3)

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

如果该标志未在程序标题中设置,系统将不会为该过程分配2GB以上的地址。

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

请记住,此功能旨在帮助端口程序无法正确处理指针 - 而不是让您编写此类程序。还要记住虚拟地址与物理地址关系不大的重要事实(换句话说,即使你的RAM少于4GB,系统仍然可以使用TB级别的虚拟地址)。

答案 1 :(得分:2)

如果程序未标记为Large-Address Aware(或者更确切地说,明确标记为而不是 Aware),这将适用于64位Windows,因为它明确表示Windows在只有一点需要注意:如果我没记错的话,指针应该在转换回64位时进行符号扩展。

无论如何都不重要,因为所有“否定”指针只能由内核代码访问,并且在用户空间代码中不可见(/LARGEADDRESSAWARE:NO标志也保护程序免受/3GB内核的影响切换会使这个肯定是假的。)

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