【问题标题】:NSNumber >= 13 won't retain. Everything else willNSNumber >= 13 不会保留。其他一切都会
【发布时间】:2011-02-01 18:21:58
【问题描述】:

我目前正在处理的代码需要将 NSNumber 对象添加到数组中。所有值为 0-12 的 NSNumber 都可以正常添加,但 13 之后会导致 EXC_BAD_ACCESS。我打开了 NSZombieEnabled,现在收到了*** -[CFNumber retain]: message sent to deallocated instance 0x3c78420

这是调用堆栈:
#0 0x01eac3a7 in ___forwarding___
#1 0x01e886c2 in __forwarding_prep_0___
#2 0x01e3f988 in CFRetain
#3 0x01e4b586 in _CFArrayReplaceValues
#4 0x0002a2f9 in -[NSCFArray insertObject:atIndex:]
#5 0x0002a274 in -[NSCFArray addObject:]
#6 0x00010a3b in -[Faves addObject:] at Faves.m:24
#7 0x000062ff in -[ShowController processFave] at ShowController.m:458
#8 0x002af405 in -[UIApplication sendAction:to:from:forEvent:]
#9 0x00312b4e in -[UIControl sendAction:to:forEvent:]
#10 0x00314d6f in -[UIControl(Internal) _sendActionsForEvents:withEvent:]
#11 0x00313abb in -[UIControl touchesEnded:withEvent:]
#12 0x002c8ddf in -[UIWindow _sendTouchesForEvent:]
#13 0x002b27c8 in -[UIApplication sendEvent:]
#14 0x002b9061 in _UIApplicationHandleEvent
#15 0x02566d59 in PurpleEventCallback
#16 0x01e83b80 in CFRunLoopRunSpecific
#17 0x01e82c48 in CFRunLoopRunInMode
#18 0x02565615 in GSEventRunModal
#19 0x025656da in GSEventRun
#20 0x002b9faf in UIApplicationMain
#21 0x00002498 in main at main.m:14

如果它没有被隔离到某个范围的 NSNumbers,我会认为我的内存管理搞砸了,但我只是不知道。

有什么想法吗?

谢谢,
乔什

【问题讨论】:

  • 这是因为 ObjC 有 triskaidekaphobia :p.

标签: objective-c iphone debugging nsnumber


【解决方案1】:

我在回答另一个问题here 时发现了数字 0 到 12 的特殊之处。请记住,这是一个实现细节,不是语言规范。

基本上,最多(包括)12 的数字会为您提供对已经存在的 NSNumber 的引用,这是可能的,因为它们是不可变的。调查显示,13 或更大的数字给出了一个单独的实例。

所以你可能 搞砸了你的内存管理:-) 只是小于 13 的数字很可能是对已经存在的数字的引用,这在这些情况下可以节省你的培根。我建议您发布更多代码,以便我们可以追踪该特定问题。


根据您对此处另一个答案的评论:

我在代码中添加了一条保留行,现在一切正常。不知道为什么。我只是要顺其自然。谢谢!

我认为您会发现,小于 13 的 NSNumber 在您获得自己的之前已经保留计数为 1(将计数增加到 2),这就是它们不会导致 EXC_BAD_ACCESS 的原因。显然,您的代码正在丢失所有您分配的数字,但系统并未释放 13 岁以下的数字,因为它们仍在使用中(保持 1 或更多的计数)。

【讨论】:

  • 令人着迷!像“数字 0 到 12 是特殊的”这样的陈述不能未经测试,你瞧,你是绝对正确的! :)
  • 哇。这是大错特错了。这是我真正讨厌 Objective-C 的地方之一。所有数字都应该是不可变的。所有字符串都应该是不可变的。 Python 做对了。
  • 有那么一秒钟,@vy32,我以为你在尝试我的回答是“非常错误”,而不是 ObjC 行为。 :-) 但我不确定我是否理解你。 NSNumber确实是不可变的,这就是使这种优化成为可能的原因(例如,您不能更改“在”NSNumber(15) 后面的数字来搞砸使用它的其他人)。
  • 嗯。不,“如此错误”适用于 Apple,而不适用于您。如果 NSNumber 是不可变的,那么为什么要让它们特别呢?或者为什么要在 12 处而不是 1M 处绘制截止点?真是太随意了……
  • 嗯,这只是一个优化。他们似乎已经决定使用最多 12 的数字,因此值得提前设置它们,或者他们有一个运行缓慢的演示时钟应用程序,他们想让它看起来更好:-) 我可能会在预分配 -1、0 和 1 时停止,因为它们是最常用的。但有一个权衡。您最多可以分配一百万,但这将使用相当多的内存来存储很多没有人会使用的数字。想想您在应用程序中需要数字 174,563 的次数。
【解决方案2】:

显然 NSNumbers >12 将保留。我建议您编写一个非常小的程序来向自己证明这一点。然后获取该程序,使其成为一个函数,并在程序的早期调用它。慢慢地将函数移动到程序中的后面位置,直到出现错误。你会因此找到你真正的错误。

【讨论】:

  • 我在代码中添加了一条保留行,现在一切正常。不知道为什么。我只是要顺其自然。谢谢!
  • @jkap 我可以建议您花时间研究一下内存管理规则并找出为什么它现在可以工作吗?如果您了解自己是如何解决此问题的,那么您以后遇到类似问题的可能性就会降低。
  • @jkap:在代码中添加随机保留将导致您最终得到无法释放的程序,这些程序会泄漏大量内存。了解保留/释放规则后,它们实际上非常清楚,因此请花点时间了解发生了什么。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-02-05
  • 2011-07-28
  • 2014-02-08
  • 1970-01-01
相关资源
最近更新 更多