是否有任何平台(如果是,哪个?)可以完成以下内容,前提是运行时检查确认虚拟内存(或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
我意识到这可能是一个可怕的黑客,完全取决于操作系统的内存管理器如何实现虚拟内存(以及编译器?),所以我纯粹出于好奇而问这个。
答案 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,那么繁荣!