[CFNumber release]: 发送给已释放实例的消息

5
以下代码在我从历史核心数据对象中记录/请求值时返回以下错误:
-[CFNumber release]: message sent to deallocated instance 0x17ea2a90

我最初认为问题出在其他地方,花费无数个小时进行调试,但没有成功。经过进一步测试,我已经确定将崩溃点定位到从历史核心数据对象请求特定值上。有人能看出来对象值被释放的原因吗?

    [[DocumentHandler sharedDocumentHandler] performWithDocument:^(UIManagedDocument *document) {

    if(!self.document) {
        self.document = document;
    }

    __block NSString *identifier = [[NSUserDefaults standardUserDefaults] objectForKey:kUserDefaultsUserIdentifier];

    [self.document.managedObjectContext performBlock:^{

        // Create history object
        History *history      = [NSEntityDescription insertNewObjectForEntityForName:@"History"
                                                              inManagedObjectContext:self.document.managedObjectContext];
        history.identifier    = identifier;
        history.followers     = [NSNumber numberWithInteger:53];
        history.following     = [NSNumber numberWithInteger:53];
        history.newFollowers  = [NSNumber numberWithInteger:53];
        history.unfollowers   = [NSNumber numberWithInteger:53];
        history.fans          = [NSNumber numberWithInteger:53];
        history.mutualFriends = [NSNumber numberWithInteger:53];
        history.nonFollowers  = [NSNumber numberWithInteger:53];

        [self.document saveToURL:self.document.fileURL forSaveOperation:UIDocumentSaveForOverwriting completionHandler:^(BOOL success) {

            // Fetch previous records
            NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"History"];
            request.predicate
            = [NSPredicate predicateWithFormat:@"identifier == %@", identifier];

            NSError *error = nil;

            NSArray *records = [self.document.managedObjectContext executeFetchRequest:request error:&error];

            [records enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
                NSLog(@"%@", [(History *)obj newFollowers]); // Crash takes place here
            }];

        }];

    }];

}];

启用异常断点后的更多日志:

    (lldb) bt
* thread #1: tid = 0x28b70, 0x3b5787fa libobjc.A.dylib`objc_release + 10, queue = 'com.apple.main-thread, stop reason = EXC_BAD_ACCESS (code=1, address=0x10)
    frame #0: 0x3b5787fa libobjc.A.dylib`objc_release + 10
    frame #1: 0x3b578022 libobjc.A.dylib`(anonymous namespace)::AutoreleasePoolPage::pop(void*) + 358
    frame #2: 0x311b4298 CoreFoundation`_CFAutoreleasePoolPop + 16
    frame #3: 0x3127533e CoreFoundation`__NSArrayEnumerate + 614
    frame #4: 0x31216012 CoreFoundation`-[NSArray enumerateObjectsWithOptions:usingBlock:] + 62
    frame #5: 0x000eae26 Twitter Followers`__71-[MainViewController updateCurrentRecordAndTableHeaderForUpdateAction:]_block_invoke_2(.block_descriptor=0x15e58080, success='\x01') + 678 at MainViewController.m:671
    frame #6: 0x3ba65bea libdispatch.dylib`_dispatch_barrier_sync_f_slow_invoke + 66
    frame #7: 0x3ba600ee libdispatch.dylib`_dispatch_client_callout + 22
    frame #8: 0x3ba629a8 libdispatch.dylib`_dispatch_main_queue_callback_4CF + 268
    frame #9: 0x3124b5b8 CoreFoundation`__CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__ + 8
    frame #10: 0x31249e84 CoreFoundation`__CFRunLoopRun + 1308
    frame #11: 0x311b4540 CoreFoundation`CFRunLoopRunSpecific + 524
    frame #12: 0x311b4322 CoreFoundation`CFRunLoopRunInMode + 106
    frame #13: 0x35eeb2ea GraphicsServices`GSEventRunModal + 138
    frame #14: 0x33a6b1e4 UIKit`UIApplicationMain + 1136

异常发生在哪一行?你能提供一个堆栈回溯吗? - Martin R
它发生在[records enumerateObjectsUsingBlock...]期间。我只是添加了进一步的日志。这些日志带有异常断点。 - morcutt
我也遇到了这个错误,但显然原因不同(没有以“new”开头的属性)。是否有可能使用其地址获取有关已释放对象的更多信息? - Symmetric
1
@Symmetric - 我知道这是一个非常古老的评论,但为了未来读者的利益,我建议您查看https://dev59.com/sWYq5IYBdhLWcg3w5kpm#14105056中讨论的“记录引用计数”功能。这在跟踪每个强引用的建立(即引用计数增加+1)和释放(即引用计数减少-1)的位置方面非常有价值。 - Rob
当我将字段类型从int更改为NSNumber *,但忘记将属性从assign更改为strong时,我遇到了这个错误。最奇怪的是,在iPhone 6 / 6s上一切正常,但在iPhone 5 / 5s上崩溃了。 - Bohdan Savych
1个回答

22

根据过渡到自动引用计数(ARC)发布说明

To allow interoperation with manual retain-release code, ARC imposes a constraint on method naming:

  • You cannot give an accessor a name that begins with new. This in turn means that you can’t, for example, declare a property whose name begins with new unless you specify a different getter:

        // Won't work:
        @property NSString *newTitle;
    
        // Works:
        @property (getter=theNewTitle) NSString *newTitle;
    

归根结底,以new开头的方法被认为返回一个由ARC负责管理和释放的对象(但这里并非如此)。我建议您只需更改属性,使其不以new开头,以避免任何混淆。


你知道是否有一种方法可以让Xcode在出现这样的字段时发出警告吗?我花了几个小时追踪malloc双重释放错误,原因是我使用new开始变量。 - Jeff Moore
@JeffMoore 我不知道有没有这样的功能。或许可以在 http://bugreport.apple.com 上提交一个好的功能请求。 - Rob
这只是一个方法命名问题(因为属性会合成访问器方法,所以也涉及到属性名称问题)。我不知道是否存在相应的变量命名考虑。 - Rob
我在使用Swift代码中的CFNumber Release时遇到了崩溃,该属性以new开头。当我将其更改为theNew时,它就可以正常工作了。谢谢。 - Dhaval Panchal
太好了,它确实有效。但在我的情况下,我正在使用@property(nonatomic,assign)NSString * skuimage; - ChenSmile
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接