ViewController responsesToSelector:消息发送到已释放实例(CRASH)


95

好的,这是交易,我讨厌提出有关调试和崩溃的问题。因为我平时处理他们自己,但我不能让我的身边这样一来,即使在已经观看多个问题

好的,所以这是问题所在,我在此堆栈跟踪中随机打开和关闭我的应用程序:

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

在哪里ViewController可以有所不同,有时会在我的代码崩溃的地方,有关联到特定的ViewController和并不拥有或调用它。

另外,要获得该控制台的跟踪信息,我已经启用了Zombies,否则我将完全不获得任何控制台打印信息,而只会得到:objc_msgSend,这意味着我正在传递已发布的消息。但是我找不到那儿...我真的被卡住了!通常,我总是调试崩溃,所以我真的很坚持。

同样,它在不同时间,不同时间在不同位置崩溃。和它崩溃的地方几乎没有任何关系ViewController。我觉得这很令人困惑。

您需要我的任何代码吗?我有很多文件,由于它在不同地方崩溃,因此分发我的代码会很麻烦!

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

感谢大家...


您是否看过以下问题:stackoverflow.com/questions/1585688/…– 2012
自我

假设您过渡到视图的方式是一致的,也许您可​​以向我们展示一个或两个示例。如果您正在执行标准的push / presentViewController调用,那应该没问题,但是我看到很多人在这里执行诸如分配/初始化视图控制器之类的操作,但不执行push / present,而是添加控制器的以子视图的形式查看。只是一个随机的例子。但是,如果没有一些代码,我们将无法诊断出来。希望有一些摘要可以帮助我们弄清楚发生了什么,让我们看看。
罗布2012年

如何启用符号断点?尝试添加以下内容:wiki.zemingo.com/index.php?title=Symbolic_Breakpoints
Stavash 2012年

@RobertRyan我使用presentModalViewController,我不将其添加为子视图
MCKapur,2012年

就我而言,我的子视图控制器包含一个webView,子VC是该WebView的scrollView的委托。我需要在dealloc / viewWillDisappear期间手动删除委托引用,否则会崩溃。希望它能帮助某人。
德莫特(Dermot)2015年

Answers:


169

使用仪器来跟踪释放的实例错误。分析您的应用程序(Cmd ⌘+ I),然后选择“ 僵尸”模板。应用程序运行后,请尝试使其崩溃。您应该得到类似的内容:

在此处输入图片说明

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

在此处输入图片说明

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

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

在此处输入图片说明

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


3
release具体来说,该问题可能不是最新的。问题是任何不平衡releaseretain对于您保持指向并稍后引用的内容,我也可能只是失败。
肯·托马斯

1
另外,我没有Zombie乐器模板,这可能是因为我使用的是Xcode Beta 4.5,同时我将切换到4.4
MCKapur,2012年

2
哦,僵尸仅在iOS模拟器中提供。我无法在iOS模拟器中运行,我使用的某些框架和库不支持该体系结构
MCKapur,2012年

只是一个小纸条。这来自xcode 5的新增功能。“僵尸工具模板在Xcode 5中得到了增强,现在支持在设备上使用。在设备上使用Zombies需要iOS7。” 这张纸条给我带来了我和2个小时的宝贵时光……
nickfox

2
如果将应用程序挂接到它时,我们的应用程序停止崩溃并停止发出“发送到已释放实例的消息”错误,这意味着什么?(当对患者进行“诊断检查”时,“疾病”就好像消失了。)
普莱西泰勒2014年

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;
      }
   }
}

不再崩溃!


我也非常感谢-只需4个小时的搜索即可找到此信息。
daidai 2014年

感谢您的发布,也遇到了同样的问题^^
Tyron

你们如何找到解决此类烦人问题的方法?脱帽!!
ViruMax 2015年

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中运行仪器:单击项目弹出菜单->编辑方案...配置文件->仪器,然后选择分配或泄漏,然后配置您的应用,然后停止仪器,单击分配中的信息按钮,然后单击“启用NSZombie检测” 。

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

我用力地敲了两个多小时,结果发现答案是一个过大的发行版,后来我用蛮力评论了我的项目副本,直到找到罪魁祸首才发现:

[viewController release];
viewController = NULL;

问题在于发行版并未将变量设置为NULL。

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

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


4

我昨天在iOS中遇到了同样的问题。我在应用程序“关于”子视图中创建了IAP,并且在“关于” viewDidLoad中添加了事务观察器。第一次购买时没问题,但是回到主窗口并输入有关子视图的再次购买后,出现了“发送到已释放实例的消息”问题,并且应用程序崩溃了。

- (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];
}

它修复了我的运行时崩溃...我在zombie购买inApp时遇到了问题。经过数小时的挖掘,我发现了这个。。。
马亨德拉

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;
    }
}

谢谢!!在这里是同样的问题。
pegpeg '16

2

在OS X中也有同样的问题。

- (void)dealloc如@SoftwareEvolved所述,要解决此方法不足。但不幸的- (void)viewWillDisappear是,仅在10.10版及更高版本上可用。

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

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

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


2

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

  1. 打开xib文件,然后从文件的所有者中,选择“显示连接检查器”右侧菜单。列出了代表,将其设置为零。
  2. (与我的情况相同)像Textfield这样的属性对象可以创建问题,因此将其委托设置为nil。
-(void) viewWillDisappear:(BOOL) animated{

[super viewWillDisappear:animated];

if ([self isMovingFromParentViewController]){

self.countryTextField.delegate = nil;

self.stateTextField.delegate = nil;

}

}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.