【问题标题】:storing a 64-bit pointer in a 32-bit integer, provided max virtual memory address <= UINT32_MAX (e.g., when RAM size <= 4GB) [closed]将 64 位指针存储在 32 位整数中,提供最大虚拟内存地址 <= UINT32_MAX(例如,当 RAM 大小 <= 4GB 时)[关闭]
【发布时间】:2013-06-21 19:46:34
【问题描述】:

如果运行时检查确认可用的虚拟内存(或 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

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

【问题讨论】:

  • 好吧,如果操作系统决定虚拟内存总是进入较低的双字,那么这可行,但老实说,我不知道有什么平台可以保证这一点。
  • 我可以告诉你,Mac OS X 不能满足你的要求。堆栈变量放置在一个地址上,其中设置了一些高位 32 位(例如 0x7FFF_5468_74DC)。 (示例代码:#include &lt;stdio.h&gt; #include &lt;inttypes.h&gt; int main(void) { int x; printf("0x%.8" PRIXPTR "\n", (uintptr_t)&amp;x); return 0; }
  • 是的,这可能会在任何满足这些限制的平台上“工作”......
  • @JonathanLeffler 有趣。我可能会尝试找出 64to32 位掩码在什么平台上可以工作。
  • 这个问题背后的动机是什么?

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


【解决方案1】:

为了帮助移植假定指针可以安全地存储在 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 范围内的虚拟地址)。

【讨论】:

    【解决方案2】:

    如果程序未标记为 Large-Address Aware(或者更确切地说,明确标记为 not Aware),这将适用于 64 位 Windows,因为在这种情况下它明确地是 Windows 所做的,只有一个警告:如果我没记错的话,指针在转换回 64 位时应该进行符号扩展。

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

    当然,只有在启动 EXE 文件时才会读取它:如果 Aware EXE 加载了非 Aware DLL,那就太好了!

    【讨论】:

    • 不,64 位进程使用 64 位指针。大地址感知仅对 32 位进程有意义。
    • 好吧,对不起。我错了。
    • @David,Michael Burr 的回答中的链接似乎表明您可以为 64 位进程禁用 largeaddressaware。这将导致 Windows 只返回小于 4GB 的指针。
    猜你喜欢
    • 1970-01-01
    • 2016-09-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-04-27
    • 1970-01-01
    相关资源
    最近更新 更多