forwardInvocation导致崩溃:com.apple.main-thread EXC_BAD_ACCESS KERN_INVALID_ADDRESS。为什么?

时间:2016-02-24 19:59:48

标签: ios objective-c multithreading cocoa-touch

此代码的存在时间远远超过我的代码,但我正试图解决这个问题。

我们有一个名为CourseManager的Singleton对象。我们还有一个名为CourseSession的对象。 CourseManager单例是唯一一个创建和保留CourseSession实例的人。

现在,在CourseSessions中,有一个NSMutableArray workingListStack

有些TableView试图像这样得到workListStack ......

self.navigationStack = [[[CourseManager sharedInstance] workingListStack] mutableCopy].

现在,CourseManager没有workingListStack,CourseSession也没有。它实现这一点的方法是通过CourseManager上的forwardInvocation函数。

- (void)forwardInvocation:(NSInvocation *)anInvocation
{
    if ([self.session respondsToSelector:anInvocation.selector]) {
        [anInvocation invokeWithTarget:self.session]; //this line
    }
    else {
        [super forwardInvocation:anInvocation];
    }
}

似乎是一种奇怪的事情。如果有人知道为什么这可能最初是这样创造的,我很乐意听到它。

无论如何,回到原点。上面代码段中的第4行在CourseSession上调用此代码...

1    - (NSMutableArray *)workingListStack
2    {
3        @synchronized(_workingListStack)
4        {
5            if (!_workingListStack || [_workingListStack count] == 0) {
6                _workingListStack = [NSMutableArray array];
7                [_workingListStack addObject:[self alphaAndOmegaRoot]];
8            }
9            else {
10               [_workingListStack replaceObjectAtIndex:0 withObject:[self alphaAndOmegaRoot]];
11           }
12           return _workingListStack;
13        }
14    }

来自Crashlytics,我收到第13行的崩溃。(崩溃:com.apple.main-thread EXC_BAD_ACCESS KERN_INVALID_ADDRESS 0x00000000d179bc17)

这似乎是崩溃的奇怪路线。这可能意味着在第3行同步的_workingListStack是零吗?尝试在nil上同步时,你会收到崩溃吗?什么可能导致这种情况?

编辑:完整的Crashlytics崩溃日志:

Thread : Crashed: com.apple.main-thread
0  libobjc.A.dylib                0x246c06d8 objc_release + 7
1  T                              0x186833 -[CourseSessionInternal workingListStack] (CourseSessionInternal.m:1003)
2  CoreFoundation                 0x24edecc4 __invoking___ + 68
3  CoreFoundation                 0x24e092ad -[NSInvocation invoke] +     292
4  CoreFoundation                 0x24e0cd47 -[NSInvocation invokeWithTarget:] + 50
5  T                              0x3ff103 -[CourseSessionManager forwardInvocation:] (CourseSessionManager.m:192)
6  CoreFoundation                 0x24edd5b1 ___forwarding___ + 352
7  CoreFoundation                 0x24e0cc88 _CF_forwarding_prep_0 + 24
8  T                              0x2c6537 -[StudentModuleListTableView resetView] (StudentModuleListTableView.m:48)
9  T                              0x2c7b4d __80-[StudentModuleListTableView observeValueForKeyPath:ofObject:change:context:]_block_invoke (StudentModuleListTableView.m:175)
10 libdispatch.dylib              0x24a77dd7 _dispatch_call_block_and_release + 10
11 libdispatch.dylib              0x24a77dc3 _dispatch_client_callout + 22
12 libdispatch.dylib              0x24a7c671 _dispatch_main_queue_callback_4CF + 1532
13 CoreFoundation                 0x24e9cfc5 __CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__ + 8
14 CoreFoundation                 0x24e9b4bf __CFRunLoopRun + 1590
15 CoreFoundation                 0x24dedbb9 CFRunLoopRunSpecific + 516
16 CoreFoundation                 0x24ded9ad CFRunLoopRunInMode + 108
17 GraphicsServices               0x26067af9 GSEventRunModal + 160
18 UIKit                          0x290d9fb5 UIApplicationMain + 144
19 T                              0x120673 main (main.m:16)
20 libdispatch.dylib              0x24aa0873 (Missing)

1 个答案:

答案 0 :(得分:0)

第一点 - 当您致电_workingListStack时,请确保nil不是@synchronized(_workingListStack)。我在文档中找不到这一点。相反,我在http://opensource.apple.com/source/objc4/objc4-437.1/runtime/objc-sync.m中找到了它:

int objc_sync_enter(id obj)
{
    int result = OBJC_SYNC_SUCCESS;

    if (obj) {
        // ... 
    } else {
        // @synchronized(nil) does nothing
        if (DebugNilSync) {
            _objc_inform("NIL SYNC DEBUG: @synchronized(nil); set a breakpoint on objc_sync_nil to debug");
        }
        result = objc_sync_nil();
    }

done: 
    return result;
}

简单测试应用程序还显示在这种情况下没有创建关键部分。

第二点 - 避免更改_workingListStack部分内的锁定对象(@synchronized)。有关详细信息,请参阅此答案:Changing the locking object inside @synchronized section