如何调试ARC删除对象时不应该

时间:2012-03-21 17:51:45

标签: ios automatic-ref-counting

我的iOS游戏中有一个案例(使用ARC编译),其中一个对象(ivar,NSMutableDictionary)在Release版本中被删除,但显然不应该这样。在Debug构建中,一切都很好。

我正在试图找出调试它的最佳方法。如果我对对象进行任何类型的检查,它就应该挂起。我知道正在使用该对象,因为应用程序崩溃,因此正在访问对象。

我使用Zombie对象来告诉对象被删除,但我不知道它在何时何地发生。

有没有办法让我看到编译器何时认为不再需要这个对象或者实际上是否正在删除它(如果它在自动释放池中,可能不会告诉我任何内容)。

有没有人有好的建议来追踪这个?我不愿意将此称为编译器错误,但我无法看到编译器如何认为此对象不再被引用,因为它在整个地方被引用。持有ivar的对象是我的所有代码都在运行的地方,所以它显然仍然存在(如果不是这样的话会发生更糟糕的事情)。

现在我只想留下一行调试代码导致该对象不被删除,但我讨厌使用该解决方案发布App。

感谢。

3 个答案:

答案 0 :(得分:1)

放置调试代码的位置在对象的dealloc方法中。你可以在这里设置一个断点(即使在发布模式下),看看它会在什么时候消失。

最可能的原因是某些代码在Release中被重新排序或删除。

当你说“它被引用到所有地方”时,你是否意味着你的物品中有对它有强烈引用的物体?记忆管理的第一条规则是保留(放入ivar)您关心的内容,并释放您不再关心的内容。如果你有关心这个对象的对象,那么它们应该有一个强大的属性指向它。如果他们这样做,那么它肯定不会消失。


ARC下的悬空强烈指示表明您的代码存在严重问题。我会首先寻找你使用桥接演员(尤其是__bridge)的任何地方。确保你没有错误地将对象交给void指针。

注意C数组的任何使用。如果你离开C数组的末尾,那么你可以破坏其他内存,这可能会导致这些问题。

同样,请注意使用length参数的任何内容,例如NSStringNSData。如果传递的值太长,则可以走掉数据末尾并破坏其他变量。类似地通过malloc内存使用原始指针的任何东西。

答案 1 :(得分:1)

我们今天遇到了一个问题,听起来就像你在这里碰到的一样。我们正在使用从plist文件加载的NSDictionary中的自定义方法加载一个类,我们的应用程序现在在该方法的末尾崩溃,因为看起来像是双版本。我们发现关闭发布二进制文件的优化就是我们可以做的一切来解决它。

我们没有将任何相关代码更改为现在导致崩溃的方法(它已经运行了大约2个月),经过几个小时试图找出问题所在,我们发现只有目前我们可以修复它的方法是将我们的发布代码的“优化级别”更改为“无”。转到..

项目 - >目标 - >二进制名称 - >构建设置 - >优化级别 - >发布

并将其设为'无-O0'。

我只能假设优化器中存在一个非常奇怪的错误,但我希望这对您有帮助!

答案 2 :(得分:1)

这也发生在我身上,但是IBOutlets很弱。

@property (nonatomic, weak) IBOutlet UIView *blahView;

…

[self.blahView removeFromSuperview];
[self.otherView addSubview:self.blahView];

在第一行编译器认为没有更多对该对象的引用并释放/ nils之后。

保持弱引用ivar并使用临时变量(在范围内)来执行此操作会使编译器无法释放它。

UIView *blahView = self.blahView;
[blahView removeFromSuperview];
[self.otherView addSubview:blahView];

这能解决您的问题吗?