95

好的,这是交易,我讨厌提出有关我的调试和崩溃的问题。因为我通常自己处理它们,但即使已经查看了多个问题,我也无法解决这个问题。

好的,这就是问题所在,我发现我的应用程序随机打开和关闭,并与此堆栈跟踪一起崩溃:

*** -[ViewController respondsToSelector:]: message sent to deallocated instance 0x1e5d2ef0

哪里ViewController可能会有所不同,有时是我的代码崩溃的地方,与那个特定的地方无关ViewController,也不拥有或调用它。

另外,为了获得控制台跟踪,我启用了 Zombies,否则我根本不会得到控制台打印,我只会得到: objc_msgSend,我知道这意味着我正在发送已发布的消息。但我找不到那在哪里......我真的被困住了!通常我总是调试我的崩溃,所以我真的坚持这一点。

同样,这在不同的时间和不同的地方崩溃,打开和关闭。而且它崩溃的地方几乎与ViewController. 我觉得这很令人困惑。

你需要我的任何代码吗?我有很多文件,由于它在不同的地方崩溃,分发我的代码将是一团糟!

我尝试添加符号断点但没有成功,并且 Zombies 在 iOS 的 Instruments 应用程序中不可用。我无法在模拟器上运行我的应用程序,因为它有不支持的架构框架。

谢谢大家...

4

7 回答 7

169

使用Instruments来追踪解除分配的实例错误。分析您的应用程序(Cmd ⌘</kbd>+I) and choose Zombies template. After your application is running, try to crash it. You should get something like that:

在此处输入图像描述

单击弹出窗口中地址旁边的箭头以显示在释放后调用的对象。

在此处输入图像描述

您现在应该看到更改了此对象的保留计数的每个调用。这可能是因为直接发送保留/释放消息以及耗尽自动释放池或插入 NSArrays。

RefCt列显示调用操作后的 retainCount,而责任调用者显示执行该操作的类名和方法。当您双击任何保留/释放时,仪器将向您显示执行此操作的代码行(如果这不起作用,您可以通过选择它并在扩展详细信息窗格中选择它的对应项来检查调用):

在此处输入图像描述

这将让您检查对象的所有retainCount生命周期,并且您可能会立即发现您的问题。您所要做的就是找到缺少的最新版本的保留

于 2012-06-23T16:12:51.520 回答
59

有类似的问题。在我的例子中,viewController 需要获取 navigationController 事件,所以它注册为导航控制器委托:

 self.navigationController.delegate = self;

当该控制器被解除分配但仍然是视图控制器的委托时,就会发生崩溃。在 dealloc 中添加此代码无效:

-(void) dealloc
{
    if (self.navigationController.delegate == self)
    {
        self.navigationController.delegate = nil;
    }

因为在调用 dealloc 时,视图控制器已经从视图层次结构中移除了,所以 self.navigationController 为 nil,所以比较肯定会失败!:-(

解决方案是添加此代码以检测 VC 在实际这样做之前离开视图层次结构。它使用 iOS 5 中引入的方法来确定视图何时被弹出而不被推送

-(void) viewWillDisappear:(BOOL) animated
{  
   [super viewWillDisappear:animated];
   if ([self isMovingFromParentViewController])
   {
      if (self.navigationController.delegate == self)
      {
           self.navigationController.delegate = nil;
      }
   }
}

没有更多的崩溃!

于 2013-08-09T00:41:46.727 回答
4

对于无法解决的任何人,这里有一些其他技术:

https://stackoverflow.com/a/12264647/539149

https://stackoverflow.com/a/5698635/539149

https://stackoverflow.com/a/9359792/539149

https://stackoverflow.com/a/15270549/539149

https://stackoverflow.com/a/12098735/539149

您可以在 Xcode 5 中运行 Instruments,方法是单击项目弹出窗口->Edit Scheme...Profile ->Instrument 并选择 Allocations 或 Leaks,然后分析您的应用程序,然后停止 Instruments,单击 Allocations 中的信息按钮和“启用 NSZombie 检测” .

但是,对于直接来自 com.apple.main-thread 的消息,这可能不会显示任何内容。

我在这个问题上敲了两个多小时,结果证明是过度发布,我通过暴力评论我的项目副本发现了这一点,直到我找到了罪魁祸首:

[viewController release];
viewController = NULL;

问题是 release 没有将变量设置为 NULL。

这意味着将其设置为 NULL 会再次调用 release,递减 refcount 并立即释放内存,直到稍后引用 viewController 的变量完成。

因此,要么启用 ARC,要么确保您的项目始终使用 release 或 NULL,但不能同时使用两者。我的偏好是使用 NULL,因为这样就没有机会引用僵尸,但它使查找对象被释放的位置变得更加困难。

于 2013-10-08T00:30:42.727 回答
4

我昨天在 iOS 中遇到了同样的问题。我在应用程序“关于”子视图中创建了 IAP,并在“关于”视图DidLoad 中添加了事务观察器。第一次购买没有问题,但是回到主窗口再次进入about subview进行购买后,出现“message sent to deallocated instance”的问题,App崩溃了。

- (void)viewDidLoad
{
    [[SKPaymentQueue defaultQueue] addTransactionObserver:self];                                           object:nil];
}

在dealloc中删除Transaction Observer后,问题就解决了。

- (void)dealloc
{
    // Even though we are using ARC, we still need to manually stop observing any
    // NSNotificationCenter notifications.  Otherwise we could get "zombie" crashes when
    // NSNotificationCenter tries to notify us after our -dealloc finished.

    [[SKPaymentQueue defaultQueue] removeTransactionObserver:self];
}
于 2015-03-25T03:50:55.467 回答
4

我有一个非常相似的问题,我发现这是由于导航控制器代表设置。

下面解决了我的问题,

- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];

    if (self.navigationController.delegate != self) {
        self.navigationController.delegate = self;
    }
}

-(void)viewWillDisappear:(BOOL)animated {
    [super viewWillDisappear:animated];

    if (self.navigationController.delegate == self) {
        self.navigationController.delegate = nil;
    }
}
于 2015-07-01T05:42:20.747 回答
2

在 OS X 中有同样的问题。

- (void)dealloc正如@SoftwareEvolved 已经说过的那样,解决这个方法还不够。但不幸- (void)viewWillDisappear的是,仅适用于 10.10 及更高版本。

我在我的 NSViewController 子类中引入了自定义方法,其中将所有僵尸危险引用设置为 nil。在我的情况下,这是NSTableView属性(delegatedataSource)。

- (void)shutdown
{
  self.tableView.delegate = nil;
  self.tableView.dataSource = nil;
}

就这样。每次我要从超级视图中删除视图时都需要调用这个方法。

于 2014-12-09T15:05:23.833 回答
2

我有同样的问题。很难找到哪个委托导致问题,因为它没有指示任何行或代码语句所以我尝试了一些方法,也许它对你有帮助。

  1. 打开 xib 文件并从文件的所有者处,选择“显示连接检查器”右侧菜单。代表被列出,将它们设置为 nil 是可疑的。
  2. (与我的情况相同)像 Textfield 这样的属性对象可能会产生问题,因此将其代表设置为零。
-(void) viewWillDisappear:(BOOL) animated{

[super viewWillDisappear:animated];

if ([self isMovingFromParentViewController]){

self.countryTextField.delegate = nil;

self.stateTextField.delegate = nil;

}

}
于 2016-01-12T05:53:29.807 回答