【问题标题】:Is the pointer guaranteed to be > a certain value?指针是否保证 > 某个值?
【发布时间】:2012-02-12 14:40:05
【问题描述】:

在 C++ 中,当我执行 new(甚至是 malloc)时,是否可以保证返回地址会大于某个值?因为......在这个项目中,我发现使用 0-1k 作为枚举非常有用。但如果有可能获得如此低的价值,我不想这样做。我唯一的目标系统是带有 OS window/linux 和 mac 的 32 位或 64 位 CPU。

标准对指针有什么规定吗? windows 或 linux 是否说明了它们的 C 运行时以及最低内存地址(对于 ram)是什么?

-edit- 我最终修改了我的new 重载以检查地址是否高于>1k。如果没有,我会调用 std::terminate 。

【问题讨论】:

  • 为什么使用枚举作为指针?
  • @Pubby:通常(特别是在解释器和游戏中)依靠特定于平台的指针特性来填充额外的信息,通常是为了消除间接性。由于对齐规则,低三位是空闲的;此外,64 位系统通常具有只有 48 位有效位的用户空间指针;其余的都是10,因此您可以将指针打包到double 的(53 位)尾数中,并将其高位设置为表示NaN。然后,低阶标志让您可以在带有掩码和移位的表示之间快速选择。
  • 看来我只需要 6 位所以我什至不需要前 1 或 4k :)。

标签: c++ memory pointers new-operator ram


【解决方案1】:

就标准而言,什么都没有。但实际上,它取决于目标操作系统,例如 windows 将前 64kb 的内存保留为无人区(取决于构建它是只读内存,否则它被标记为 PAGE_NOACCESS),而它使用内核内存的上限 0x80000000+,但可以更改,请参阅 MSDN 上的 thisthis

在 x64 上,您还可以使用地址的高位(目前只有 47 位用于地址),但这不是一个好主意,因为稍后它会改变并且您的程序会中断(制定标准的 AMD也建议不要这样做)。

【讨论】:

    【解决方案2】:

    没有这样的保证。如果您需要非常特定的内存位置,您可以尝试使用placement new,但它有一些问题,您必须使用work hard to avoid。您为什么不尝试使用带有整数键的映射,该键将指针作为其值呢?这样您就不必依赖特定的内存地址和范围。

    【讨论】:

      【解决方案3】:

      理论上,不——甚至不能保证指针 > 0。但是,在实践中,将其视为无符号整数(不要忘记指针可能具有高阶“1”位),不我所知道的系统的指针值会小于大约 1000。但依赖它就是依赖于“未定义的行为”。

      【讨论】:

      • 参考?我想我记得读过 linux 虚拟内存中的前 1GB 仅用于内核,[所以如果这是真的,您的应用程序将不会在前 1GB 中获得地址,除非它在内核模式下运行] 但是,我可能是最初的假设是错误的,我不记得我在哪里读过它:\
      • @amit my google-fu 想出了这个linux-mm.org/HighMemory“3GB 用于用户程序,1GB 用于内核”
      • @amit -- 我说的很笼统 -- C++ 在一些非常小的系统上运行。
      • 在 Linux 上,内核-用户空间划分在内核中是可配置的,因此至少 3 个拆分:1-3 GB、2-2 GB 和 3-1 GB 在 32 位上是常见的系统。此链接有些旧但非常详细:kerneltrap.org/node/2450
      【解决方案4】:

      对于有效内存地址的来源没有标准;要编写安全的独立于系统的代码,你不能依赖某些地址(即使有轶事支持,你也不知道什么时候会随着新的系统更新而改变)。

      【讨论】:

        【解决方案5】:

        它是非常特定于平台的,因此我不鼓励依赖此类信息,除非您有充分的理由并且意识到对可移植性、可维护性等的影响。

        NULL 保证始终为 0x0。如果我没记错的话,x86 将前 128 MB 的地址空间保留为“NULL 等效”,因此有效指针不能采用此范围内的值。在 x64 上,有一些 additional addresses 在实践中你不应该遇到,至少现在是这样。

        至于为操作系统保留的地址空间,显然取决于操作系统。在 Linux 上,内核-用户空间划分在内核中是可配置的,因此至少 3 个划分:1-3 GB、2-2 GB 和 3-1 GB 在 32 位系统上很常见。您可以找到更多详细信息on kerneltrap

        【讨论】:

        • 您的意思是地址空间的前 128 个 K B?
        • @CodyGray 不,它实际上是 128 MB,而不是 kB。但我对原因并不完全正确。它不是由 CPU 本身引起的,而是由大多数类 UNIX 系统上应用程序地址空间的布局引起的。 0-128 MB 区域是为堆栈保留的,这意味着当使用从堆中分配内存的newmalloc() 时,您不会从该范围内获得地址。 this nice answer 里解释的很好。
        猜你喜欢
        • 2011-06-27
        • 1970-01-01
        • 2021-12-23
        • 1970-01-01
        • 2014-09-27
        • 2012-07-23
        • 1970-01-01
        • 2022-01-01
        • 1970-01-01
        相关资源
        最近更新 更多