该物体是如何过早释放的?

时间:2010-09-26 02:17:32

标签: iphone objective-c crash release

我收到了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已损坏。我很怀疑这是答案,因为那些二进制文件已被检查,但我在这里已经没有想法了。如果它再次在测试仪的手机上崩溃,我不想再重新提交。

1 个答案:

答案 0 :(得分: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.
    }
}

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