将64位指针存储在32位整数中,提供最大虚拟内存地址

时间:2022-09-01 11:15:15

Are there any platforms (if so, which?) where something like the following can be done, provided that a runtime check confirms that there is no more than 4GB of virtual memory (or RAM) available?

是否存在任何平台(如果是,哪个?),只要运行时检查确认不超过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;

and to get back the original pointer:

并获取原始指针:

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

I realize this would probably be a terrible hack and entirely dependent on how the OS's memory manager implements virtual memory (as well as the compiler?), so I'm asking this purely out of curiosity.

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

2 个解决方案

#1


3  

In order to aid porting crufty, old 32-bit programs that assumed that pointers could be safely stored in 32-bit integer types, Windows still respects the IMAGE_FILE_LARGE_ADDRESS_AWARE flag in the PE header for 64-bit programs.

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

If that flag isn't set in the program's header, the system will not allocate an address above 2GB to the process.

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

By default for 64-bit builds, the linker sets the flag (ie., by default the address space for a 64-bit program will not be limited). If you want to indicate that your 64-bit program should not be given any address space above 2GB, pass the /largeaddressaware:no option to the linker when the program is built. See http://msdn.microsoft.com/en-us/library/windows/desktop/aa384271.aspx for details.

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

Keep in mind that this feature is intended to help port programs that don't handle pointers properly - not to enable you to write such programs. Also keep in mind the important fact that virtual addresses have little to do with physical addresses (in other words, even if you have less than 4GB of RAM, the system could still use virtual addresses in the terabyte range).

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

#2


2  

This would work on a 64-bit Windows if the program is not marked as Large-Address Aware (or rather, is explicitly marked as not Aware), since it's explicitly what Windows does in that case, with just one caveat: If I remember correctly, pointers should be size-extended when converting back to 64 bits.

如果程序没有被标记为大地址识别(或者更确切地说,被明确标记为不知道),这将适用于64位Windows,因为它明确是Windows在这种情况下所做的事情,只有一点需要注意:如果我记得正确地说,当转换回64位时,指针应该是大小扩展的。

Not that it would matter anyway, since all "negative" pointers are accessible only to kernel code and should not be visible in userspace code (the /LARGEADDRESSAWARE:NO flag also protects the program from the /3GB kernel switch which would make this affirmation false).

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

Of course, it's only read when starting an EXE file: If an Aware EXE loads a non-Aware DLL, boom!

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

#1


3  

In order to aid porting crufty, old 32-bit programs that assumed that pointers could be safely stored in 32-bit integer types, Windows still respects the IMAGE_FILE_LARGE_ADDRESS_AWARE flag in the PE header for 64-bit programs.

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

If that flag isn't set in the program's header, the system will not allocate an address above 2GB to the process.

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

By default for 64-bit builds, the linker sets the flag (ie., by default the address space for a 64-bit program will not be limited). If you want to indicate that your 64-bit program should not be given any address space above 2GB, pass the /largeaddressaware:no option to the linker when the program is built. See http://msdn.microsoft.com/en-us/library/windows/desktop/aa384271.aspx for details.

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

Keep in mind that this feature is intended to help port programs that don't handle pointers properly - not to enable you to write such programs. Also keep in mind the important fact that virtual addresses have little to do with physical addresses (in other words, even if you have less than 4GB of RAM, the system could still use virtual addresses in the terabyte range).

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

#2


2  

This would work on a 64-bit Windows if the program is not marked as Large-Address Aware (or rather, is explicitly marked as not Aware), since it's explicitly what Windows does in that case, with just one caveat: If I remember correctly, pointers should be size-extended when converting back to 64 bits.

如果程序没有被标记为大地址识别(或者更确切地说,被明确标记为不知道),这将适用于64位Windows,因为它明确是Windows在这种情况下所做的事情,只有一点需要注意:如果我记得正确地说,当转换回64位时,指针应该是大小扩展的。

Not that it would matter anyway, since all "negative" pointers are accessible only to kernel code and should not be visible in userspace code (the /LARGEADDRESSAWARE:NO flag also protects the program from the /3GB kernel switch which would make this affirmation false).

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

Of course, it's only read when starting an EXE file: If an Aware EXE loads a non-Aware DLL, boom!

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