64位系统上的指针值范围
最近我在阅读关于小字符串优化(SSO):What are the mechanics of short string optimization in libc++?。正如我们所知,一个字符串通常由3个指针组成,这些指针在64位系统上是24个字节。链接的答案表明,在libC++的实现中,第一个指针的第一位用于指示字符串是处于“长”还是“短”模式,即堆分配和外部存储与内部存储的最多约22个字符。64位系统上的指针值范围
然而,这却假设第一个指针的第一位永远不能成为地址的一部分,因为无论何时字符串处于“long”模式,该位总是被设置(或取消设置,取决于哪种约定是选择)。这看起来似乎是合理的,因为使用64位指针可以实现2^64个地址,大于1后接18个字节,或超过10亿GB。
所以这是合理的,虽然不确定。我的问题是:这是有保证的地方吗?如果有保证,它在哪里保证?按照架构规范,还是由其他东西?更进一步:这样做有多少位是安全的?我有一个模糊的回忆,只有48位被使用,但我不记得。
如果存在一些比特数,例如, 8或16保证不被触动,这当然是可以用一些有趣的方式来利用的东西。利用这一点会很好,但不会以代码在某些机器上神秘失败为代价。
正如我们所知,一个字符串通常由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更好的做法,因为你的应用程序正在控制这些。
“长位”不是指针的一部分,但容量:
struct __long
{
size_type __cap_;
size_type __size_;
pointer __data_;
};
的“绝招”是,如果你总是分配偶数个字符,储备一个用于nul结束符,结果容量将始终为奇数。你可以免费获得1位!
感谢您指出这一点,我愚蠢地认为,字符串使用像矢量一样的3个指针通常会,绝对是一个大脑屁。我接受zneak的答案,因为他添加了更多关于我的问题核心的信息,但也要感谢你! –
Itanium和Alpha是非常不同的平台。关于你能做的最好的事情是做出有关操作系统使用的内存布局的陈述。 – Flexo
@ Flexo好吧,这已经是部分答案,如果Itanium规范有话要说,那么这是一个开始。 –
已经投票结束了?我可以问为什么? –