【问题标题】:How is this object being prematurely released?这个对象是如何被提前释放的?
【发布时间】:2010-09-26 02:17:32
【问题描述】:

我收到了来自 Apple 的崩溃报告,我正试图确定发生了什么。我无法按照他们的步骤重新创建崩溃,并且在我的任何测试中都没有看到类似的崩溃。以下是崩溃报告的重要部分:

9   libobjc.A.dylib                 0x00004838 objc_exception_throw + 64
10  CoreFoundation                  0x000a167c -[NSObject(NSObject) doesNotRecognizeSelector:] + 96
11  CoreFoundation                  0x000491d2 ___forwarding___ + 502
12  CoreFoundation                  0x00048f88 _CF_forwarding_prep_0 + 40
13  TheApp                          0x0001cd28 -[Tumblelog initWithDictionary:] (Tumblelog.m:40)
14  TheApp                          0x0001ef8c -[TumblrEngine userFromRequest:] (TumblrEngine.m:589)

在我看来,这就像我的字典被提前发布了。在应用程序的大多数运行期间,此代码路径被多次调用,它还没有对我造成崩溃,所以我相信我不会不小心将错误的对象发送到 initWithDictionary

这是来自TumblrEngineTumblelog 的代码。

// TumblrEngine.m
- (TumblrUser *)userFromRequest:(ASIHTTPRequest *)request{
    NSData *data = [request responseData];
    NSError *parseError = nil;
    NSXMLDocument *doc = [[[NSXMLDocument alloc] initWithData:data options:NSXMLDocumentTidyXML error:&parseError] autorelease];
    NSDictionary *dictionary = [doc toDictionary];
    NSDictionary *userDict = [dictionary valueForKeyPath:kParseKeyPathUserInfo];
    TumblrUser *user = [[TumblrUser alloc] initWithDictionary:userDict];
    NSArray *tumblelogs = [dictionary valueForKeyPath:kParseKeyPathTumblelogsInfo];
    NSMutableArray *userTumblelogs = [NSMutableArray array];
    for(NSDictionary *tumblelogDictionary in tumblelogs){
        Tumblelog *tumblelog = [[Tumblelog alloc] initWithDictionary:tumblelogDictionary]; //line 589
        [userTumblelogs addObject:tumblelog];
        [tumblelog release];
    }
    [user setTumblelogs:userTumblelogs];
    return [user autorelease];

}

// Tumblelog.m
- (id)initWithDictionary:(NSDictionary *)aDictionary{
    if((self = [super init])){
        [self setAvatarURL:[aDictionary restURLForKey:kParseKeyTumblelogAvatarURL]]; //line 40
        // this was the line that started the crash
    }
    return self;
}

我的主要问题是:你知道aDictionary 在创建和我尝试在Tumblelog.m 中使用它之间的任何时间点是如何被释放的吗?

否则,我正在探索在 NSDictionary 上加载类别是否有问题。当我将应用程序直接加载到我的三部测试手机(iPhone 4/iOS 4.1、iPhone 3GS/iOS 4.0.1、iPhone 3G/3.1.3)上时,它运行良好。该应用程序崩溃的手机是 iPhone 4/iOS 4.1,与我的主要测试手机相同。

我唯一能想到的可能是我发送给 Apple 的二进制文件中的某些内容已损坏。我怀疑这是答案,因为这些二进制文件是校验和的,但我在这里没有想法了。如果它会在测试人员的手机上再次崩溃,我不想只是重新提交。

【问题讨论】:

  • 很遗憾,您无法重新创建崩溃。在我看来,从堆栈跟踪来看,您传递给 -[Tumblelog initWithDictionary:] 的任何内容实际上都不是 NSDictionary。然后该方法对其调用 NSDictionary 方法,导致“无法识别选择器”异常。您确定 tumblelogs 数组中的每个对象始终是一个 NSDictionary(即文档的 toDictionary 中键 kParseKeyPathTumblelogsInfo 的值始终是一个 NSDictionaries 数组)?
  • 我不熟悉 NSXMLDocument toDictionary (并且找不到文档?)知道这一点,但可以保证[dictionary valueForKeyPath:kParseKeyPathTumblelogsInfo] 将返回一个 NSArray 的 NSDictionary 实例吗?您根本没有进行任何错误检测,即传入数据符合您期望的 XML。
  • 非常好的点。接收格式与我预期不同的响应数据肯定是问题所在。我正计划像@imaginaryboy 建议的那样添加错误检查。在正常情况下,格式错误的 XML 响应不会深入到代码中,它们会更早地被发现。我担心这不是问题,我只是重新提交一个会再次被拒绝的应用程序。

标签: iphone objective-c crash release


【解决方案1】:

这可能是一个线程问题(对象在另一个线程上释放),但对于上面的代码来说,这似乎不太可能。

更有可能(正如@imaginaryboy 所说)你并没有真正的字典。

一个更安全的循环看起来像这样。

for(id tumblelogDictionary in tumblelogs){
    if ([tumblelogDictionary isKindOfClass:[NSDictionary class]]) {
        Tumblelog *tumblelog = [[Tumblelog alloc] initWithDictionary:tumblelogDictionary]; //line 589
        [userTumblelogs addObject:tumblelog];
        [tumblelog release];
    } else {
        // Appropriate error handling and / or logging.
    }
}

注意:我实际上并没有尝试编译这个。它可能有一两个错字或语法错误。

【讨论】:

  • 谢谢。在这种情况下,只检查数组中是否有字典是可以接受的。除非其他人有想法,否则我可以在不接收字典数组的情况下达到这一点的唯一方法是从服务器获取格式错误的 HTML。如果是这种情况,将tumblelog 留空将是可接受的结果。
猜你喜欢
  • 2010-12-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-08-20
  • 2010-11-30
  • 1970-01-01
  • 2011-02-15
  • 2011-11-16
相关资源
最近更新 更多