64位系统上的指针值范围

时间:2016-01-13 20:28:58

标签: c++ c pointers

最近我读到了关于小字符串优化(SSO):What are the mechanics of short string optimization in libc++?。我们知道,字符串通常由3个指针组成,在64位系统上为24个字节。链接的答案说,在libc ++的实现中,第一个指针的第一个位用于指示字符串是否在" long"或"短"模式,即堆分配和外部存储与内部存储最多约22个字符。

然而,

然而,假设第一个指针的第一位不能有意义地成为地址的一部分,因为每当字符串在" long"模式,该位将始终设置(或取消设置,具体取决于选择的约定)。这似乎是合理的,因为64位指针允许2 ^ 64个地址,大于1,后跟18个零字节,或超过10亿千兆字节。

所以这是合理的,但不确定。我的问题是:这在某个地方得到保证吗?如果有保证,它在哪里得到保证?根据架构规范,还是通过别的东西?更进一步:有多少位可以安全地执行此操作?我有一个模糊的回忆读取,只使用48位,但我不记得。

如果有一些位数,例如8或16保证不受影响,这肯定是可以通过一些有趣的方式利用的东西。利用它会很好,但不能以某些机器上的代码神秘失败为代价。

2 个答案:

答案 0 :(得分:4)

  

众所周知,字符串通常由3个指针组成,在64位系统上为24个字节。

libc ++不是这样。 __long结构,用于"长字符串"定义为:

struct __long
{
    size_type __cap_;
    size_type __size_;
    pointer   __data_;
};

短旗因此进入了容量领域,使得整个事情没有实际意义。

对于指针标记,没有关于指针大小的通用保证。在x86_64上,CPU用于虚拟地址转换的数据结构仅使用48位(或物理地址扩展为52位),因此虚拟地址永远不会使用高16位(或12位)。此外,大多数操作系统将其内核映射到每个进程并为其保留一定量的高端地址空间,因此在实践中,用户模式指针甚至更受限制。在Windows上,指针最重要的硬件可用位告诉它是属于内核空间还是用户空间。

这些限制可能会在未来发生变化,并且会因平台而异,因此在与平台无关的标准库中使用它们会很糟糕。一般而言,use the least-significant bits for pointer tagging的实践要好得多,因为您的应用程序可以控制这些。

答案 1 :(得分:3)

“长位”不是指针的一部分,而是容量的一部分:

top:80%;

“技巧”是如果你总是分配偶数个字符并为nul终结符保留一个字符,那么结果容量将始终是奇数。你可以免费获得1位数!