ios - 内存地址是否遵循 iOS 中的模式?

标签 ios objective-c memory memory-management

我在我的应用程序中比较两个 NSNumbers,但我做错了:

if(max < selected)

它应该是:

if([max longValue] < [selected longValue])

所以第一个比较实际上是比较两个对象的内存地址,有趣的是(至少对我而言)是值似乎与地址有关。例如,如果我得到第一个值为 5 的数字,它的内存地址是 0xb000000000000053 如果我得到第二个值为 10 的是 0xb0000000000000a3(“a”相当于十六进制的 10)。

因此,第一个比较(错误)实际上是有效的。现在一个用户提示这里有一个错误,显然是因为这个,但它让我想到了下一个问题:

这是否只发生在模拟器中?因为它是我正在测试的地方,用户将拥有一个真实的设备。或者也许这通常会发生,但它不是一个总是满足的规则?

最佳答案

这是一个“标记指针”,而不是地址。如您所见,值 5 包含在指针内。您可以识别标记指针,因为它们是奇数(最后一位是 1)。不可能在任何 Apple 硬件上获取奇数地址(字大小为 4 或 8 字节),因此该位永远不会设置为真实地址。

标记指针仅在 64 位平台上可用。如果您在 32 位平台上运行,那么这些值将是真正的指针,并且它们可能没有任何特定的顺序,这将导致您遇到的各种错误。不幸的是,我不认为有任何方法可以获得编译器警告,甚至是针对 NSNumber 上的这种滥用的静态分析警告。

Mike Ash provides an in-depth discussion of the subject.

稍微相关一点,在 32 位平台上,某些 NSNumber 是单例,特别是小值,因为它们被大量使用(我记得是 -1 到 12,但我相信它在不同的平台上是不同的)。这意味着 == 可能碰巧适用于某些数字,但不适用于其他数字。这也意味着在没有 ARC 的情况下,可能会过度释放特定值(例如 4),这样您的程序在下次碰巧使用该值时就会崩溃。真实的故事....很难调试。

关于ios - 内存地址是否遵循 iOS 中的模式?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58557989/

相关文章:

ios - performSegue :withSender: sender object

c - 为什么在任意内存位置设置值不起作用?

PHP SimpleXML 大文件没有额外的内存使用

ios - 当呈现 Controller 为模式时,未调用 UIAlertAction 闭包

ios - 使用 Google API 在 Objective C 中查询共享的 Google 日历

iOS MDM : Configure iOS device as supervised through MDM server

ios - Segue 不传递值

memory - Spark : what's the advantages of having multiple executors per node for a Job?

ios - swift 如何处理 session 中的 nsjson

ios - 嵌套的 SplitviewController