所以我不确定应该如何处理它们:有符号的优点是在0附近是安全的,因为那里没有间断,而无符号的优点是在2^63附近,因为那里没有间断。然而,在实践中,您看不到任何接近2^63的地址,因为当前商品硬件的虚拟地址空间被限制在50位以下。这是指签名吗?
1...,有时堆和其他映射区域不靠近地址空间的底部或顶部。
TL:DR:intptr_t
在某些情况下可能是最好的,因为有符号溢出边界位于“非规范洞”的中间。如果可以从零换行到0xff...ff
或反之亦然,那么将值视为负值而不是巨大值可能会更好,但是任何有效大小的指针+size都不能将值从int64_max
换行到int64_min
。
否则,您可能希望“high half”(high bit set)的无符号值与下半部分的值相比较。
这完全取决于你想知道关于两个指针的什么!
是的,对于从具有合理大小的相同对象派生的“相关”指针,有符号比较在当前硬件上是安全的,并且只能在不太可能的/遥远的未来的机器上中断,这些机器具有对完全64位虚拟地址的硬件支持。如果两个指针都在规范范围的下半部分,重叠检查也是安全的,我认为所有主流x86-64操作系统上的用户空间地址都是这样。
正如您所指出的,如果ptrb-c
换行(无符号换行),则无符号ptra
C
大小更接近0的静态地址,可能会发生这种情况。
通常,低64kib是不可映射的(例如,在Linux上,大多数distro都附带sysctl
vm.mmap_min_addr=65536
,或者至少4096。但是有些系统对WINE来说=0
)。不过,我认为内核不给你一个零页是正常的,除非你特别请求这个地址,因为它可以防止NULL deref出错(出于安全性和可调试性的原因,这通常是非常理想的)。
那么,它什么时候会出现带签名的比较失败呢?当
ptrb-c
在溢出时签名环绕时。或者,如果您曾经有指向high-half对象的指针(例如,指向Linux的vDSO页面),那么比较high-half和low-half地址可能会给您一个意想不到的结果:您将看到“high-half”地址小于“low-half”地址。即使ptrb-c
计算没有换行,也会发生这种情况。
(我们只直接讨论asm,不讨论C,所以没有UB,我只是使用C表示
sub
或lea
/cmp
/JL
。)
有符号环绕只能发生在
0x7fff...
和0x8000...
之间的边界附近。但这一界限与任何规范地址相去甚远。我将从另一个答案中重现x86-64地址空间的图表(对于虚拟地址为48位的当前实现)。请参见为什么在64bit中,虚拟地址比物理地址(52 bit长)短4 bit(48 bit长)?。
+----------+
| 2^64-1 | 0xffffffffffffffff
| ... | high half of canonical address range
| 2^64-2^47| 0xffff800000000000
+----------+
| |
| unusable | Not to scale: this is 2^15 times larger than the top/bottom ranges.
| |
+----------+
| 2^47-1 | 0x00007fffffffffff
| ... | low half of canonical range
| 0 | 0x0000000000000000
+----------+
Intel为57位虚拟地址提出了一个5级页表扩展(即另一个9位级别的表),但这仍然使大部分地址空间不规范。也就是说,任何规范地址离带签名的环绕仍然有2^63-2^57的距离。
根据操作系统的不同,您的所有地址可能是在低的一半或高的一半。例如,在x86-64 Linux上,高(“负”)地址是内核地址,而低(带符号的正)地址是用户空间。但是请注意,Linux将内核vDSO/vsyscall页面映射到靠近虚拟地址空间顶部的用户空间中。(但是它在顶部保留了未映射的页面,例如,
FFFFFFFFFF600000-FFFFFFFFF601000[vsyscall]
在我的桌面上的64位进程中,但是vDSO页面靠近底部一半规范范围的顶部,0x00007FFF...
。即使在理论上整个4GIB可由用户空间使用的32位进程中,vDSO也位于最高页面的下方,而MMAP(MAP_FIXET)
在最高页面上不起作用。可能是因为C允许一个过去结束指针吗?)
如果在
vsyscall
页面中获取函数或变量的地址,可以混合使用正地址和负地址。(我不认为有人会这么做,但这是可能的。)
因此,如果没有区分正负符号的内核/用户拆分,那么有符号的地址比较可能是危险的,并且您的代码在遥远的将来运行时,/if x86-64已经扩展到完全的64位虚拟地址,因此对象可以跨越边界。后者似乎不太可能,如果你能从假设它不会发生中获得加速,这可能是一个好主意。
这意味着符号比较对于32位指针来说已经很危险了,因为64位内核使得整个4GIB可以由用户空间使用。(32位内核可以配置为3:1的内核/用户拆分)。没有不可用的规范范围。在32位模式下,对象可以跨越带符号环绕的边界。(或者在ILP32 x32 ABI中:长模式下的32位指针。)
Core2只能宏融合
cmp
与无符号的比较,而不能宏融合有符号的比较,但是Core2在64位模式下根本不能宏融合。(顺便说一句,它可以在32位模式下宏融合test
和有符号比较。)
Nehalem可以宏融合
test
或cmp
与有符号或无符号比较(包括在64位模式下)。
资料来源:Agner Fog的microarch PDF。
但我会得到另一个例外 java.lang.UnsatisfiedLinkError:dlopen失败:“/data/app/com.example.user.project/lib/x86/libtracker.so”是64位而不是32位 我可以看到我的库已经成功构建,这是它在构建时显示的跟踪消息 这是我的CMakeLists 这是我的母语-lib.cpp 那么,Android studio无法从
问题内容: 我有一个网络应用程序,允许用户上传pkcs12。我将pkcs12作为二进制存储在数据库中。有什么办法让我知道pkcs12中的证书是自签名的还是CA签名的? 我正在tomcat上运行Java Web应用程序,并且可以使用openssl。 问题答案: 但是,我认为还有一些更重要的事情要解决- 为什么 人们想了解自签名证书。目标是什么?解决了什么问题?在大多数情况下,可能尝试将证书分为自签名
问题内容: 在Java中,是否保证int始终为32位,而长为64位,而不管体系结构是32位还是64位? 问题答案: Java是平台无关的。所以是32位,并且是64位的。
比较标签用于简单的变量比较,复杂的判断条件可以用if标签替换,比较标签是一组标签的集合,基本上用法都一致,如下: <比较标签 name="变量" value="值"> 内容 </比较标签> 或 <比较标签 name="变量" value="值"> 内容 <else/> 内容2 </比较标签> TP5支持的比较标签分别是: | 标签 | 含义 | | --- | --- | | eq或者 equ
请参考:http://www.kancloud.cn/manual/thinkphp/1809
比较标签用于简单的变量比较,复杂的判断条件可以用if标签替换,比较标签是一组标签的集合,基本上用法都一致,如下: <比较标签 name="变量" value="值"> 内容 </比较标签> 或 <比较标签 name="变量" value="值"> 内容 <else/> 内容2 </比较标签> TP5支持的比较标签分别是: | 标签 | 含义 | | --- | --- | | eq或者 equ