首页 > 解决方案 > Do memory addresses follow a pattern in iOS?

问题描述

I'm comparing two NSNumbers in my app and I've done it the wrong way:

if(max < selected)

And it should be:

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

So the first comparison is really comparing the two object memory addresses, the funny thing (at least for me) is that the values seems to be related with the addresses. For example, if I get the first number with value 5 its memory address is 0xb000000000000053 and if I get the second with 10 is 0xb0000000000000a3 (being "a" equivalent to 10 in hexadecimal).

For that reason the first comparison (wrong) was actually working. Now an user complaint about an error here and is obviously because of this but it has lead me to the next questions:

Does this only happen in simulators? Cause it's where I'm testing, and the user will have a real device. Or maybe this happen normally but it's not a rule always fulfilled?

标签: iosobjective-cmemorymemory-management

解决方案


This is a "tagged pointer," not an address. The value 5 is packed inside the pointer as you've seen. You can identify tagged pointers because they're odd (the last bit is 1). It's not possible to fetch odd addresses on any of Apple's hardware (the word size is 4 or 8 bytes), so that bit is never set for a real address.

Tagged pointers are only available on 64-bit platforms. If you run on a 32-bit platform then the values will be real pointers, and they may not be in any particular order, which will then lead to the kinds of bugs you're encountering. Unfortunately I don't believe there is any way to get a compiler warning or even a static analysis warning for this kind of misuse on NSNumber.

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

On a slightly related note, on 32-bit platforms, certain NSNumbers are singletons, particularly small values since they're used a lot (-1 through 12 as I recall, but I believe it's different on different platforms). This means that == may happen to work for some numbers, but not for others. It also means that without ARC, it was possible to over-release a specific value (for example, 4) such that your program would crash the next time it happened to use that value. True story.... very hard to debug.


推荐阅读