【问题标题】:How do I avoid a zombies error with xcode 4.5 w/o ARC?如何避免 xcode 4.5 w/o ARC 出现僵尸错误?
【发布时间】:2012-10-12 15:58:08
【问题描述】:

当我在启用了僵尸程序的 xcode 4.5.1 (LLDB) 调试器中运行不使用 ARC 的应用程序时,在调用 -[super dealloc] (-[NSObject dealloc] ):

* -[V2APIClient 类]:发送到已释放实例 0x9d865c0 的消息 * -[V2APIClient 类]:消息发送到释放的实例 0x9d865c0

当我在 xcode 4.4.1 (LLDB) 调试器中运行相同的应用程序时,我会收到一次错误消息 (1)。 当我在 XCode 4.3.2 中运行同一应用程序的稍早版本时,我根本没有收到错误消息 (0)。我将使用相同/最新的代码重试此操作。

仅供参考 - 这似乎与其他帖子完全相同,尚未得到回答: -[Foo class]: message sent to deallocated instance on [super dealloc])

我试图避免重复发布相同的问题两次,但有人建议我继续: https://meta.stackexchange.com/questions/152226/avoiding-asking-a-question-thats-already-been-asked

另外,我还在 Apple 开发者论坛中问了同样的问题: https://devforums.apple.com/thread/171282

最后,这是我的课的精髓:

@interface ASIHTTPRequestHandler : NSObject {
  id _error;
}
@property (nonatomic,retain) id error;
@end

@implementation ASIHTTPRequestHandler
@synthesize error = _error;
-(id)init
{
    self = [super init];
    if (self)
    {
        self.error = nil;
    }
    return self;
 }

 -(void)dealloc
 {
     self.error = nil;
     [super dealloc];// this is the line that appears to cause the problems
  }
  @end

请帮我解决这个问题。 我不相信我违反了任何内存管理规则,但这个错误似乎暗示了其他情况。在解决此问题之前,我很犹豫是否要签入任何新代码。

谢谢, 查克

附言为了记录,这里是调用代码:

PanoTourMgrAppDelegate *ptmAppDlgt = [PanoTourMgrAppDelegate getApplicationDelegate];
Settings *settings = ptmAppDlgt.settings;
Identification *identification = ptmAppDlgt.identification;
V2APIClient *v2ApiClient = [[V2APIClient alloc] initWithSettings:settings identification:identification];
NSDictionary *result = [v2ApiClient get_application_status];
BOOL success = [v2ApiClient callWasSuccessful:result];
if (!success)
{
    id error = v2ApiClient.error;
    NSString *mbTitle = nil;
    NSString *mbMessage=nil;
    if ([error isKindOfClass:[NSString class]])
    {
        mbTitle = @"Application version no longer suppported";
        mbMessage = (NSString*)error;
        [MessageBox showWithTitle:mbTitle message:mbMessage];
    }
}
[v2ApiClient release]; // This is the line that indirectly causes the messages above

【问题讨论】:

  • 问题不太可能是上面代码的结果,而是你如何alloc/init对象以及你最终如何release它。除非你正在做一些奇怪的事情,否则它必须是一个简单的过度释放案例。虽然 H2CO3 的建议很有趣,但我相信他并不是在建议盲目地插入 retain 语句,因为除非您非常幸运,否则您最终只会泄漏而不是过度释放。您只需要检查并确保增加retainCount 的所有内容都被retainCount 的适当版本所抵消。

标签: objective-c ios memory-management automatic-ref-counting


【解决方案1】:

如果您正在向已释放的实例发送消息,那是因为您没有正确管理内存。你有没有被保留平衡的释放;过度释放。

首先,对您的代码进行“构建和分析”。修复发现的任何问题。

接下来,在启用了僵尸检测的 Instruments 下运行,并打开引用计数跟踪功能。然后,当它崩溃时,检查相关对象的所有保留/释放事件。你会发现一个额外的版本。挑战在于将保留插入到正确的位置以平衡发布。

(正如 Rob 正确指出的那样,这可能只是额外调用 release 的情况。)

【讨论】:

  • 我已经进行了构建和分析,并修复了所有发现的问题。
  • 那你做了“下一个”部分吗?
  • +1 表示“构建和分析”。关于“挑战是将保留保留在正确的位置以平衡发布”,我同意。但有时反过来是正确的,你应该删除你无关的release。关键是它们需要平衡。 (我知道你知道那个 bbum,但我这样说是为了 @ChuckDoucette。)
  • 我知道如何使用应用程序运行仪器并选择 Zombies 工具。不知道怎么开启引用计数跟踪功能。
  • 这原来是由调试器在僵尸对象上调用class 方法引起的,不一定是代码中的问题。它在更高版本的 Xcode 中得到修复。请参阅我对简单测试用例的回答。
【解决方案2】:

这是某些 Xcode 版本的调试器中的错误。

我刚刚在 Xcode 4.4.1 中拥有它,但它不在 Xcode 4.6 中。为了解决这个错误,我创建了一个新的“单视图应用程序”项目,在方案对话框中打开“启用僵尸对象”,并在视图控制器中运行以下代码,并在最后一行设置断点。

- (void)viewDidLoad {
    [super viewDidLoad];

    NSObject *object = [[NSObject alloc] init];
    [object release];

}

这会在调试器中产生以下消息:

-[NSObject 类]:消息发送到已释放实例 0x6a7e330

您还可以在调试器的变量部分中看到该对象现在将其类描述为_NSZombie_。如果删除断点,则不再显示消息。 class 方法的调用是由调试器在对象被正确释放后进行的。

【讨论】:

    猜你喜欢
    • 2017-08-23
    • 1970-01-01
    • 2019-12-31
    • 1970-01-01
    • 2021-11-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多