-[NSResponder _tryRetain] 崩溃

-[NSResponder _tryRetain] crash

我遇到了用户崩溃问题。 这个:

Crashed Thread:        0

Exception Type:        EXC_BAD_INSTRUCTION (SIGILL)
Exception Codes:       0x0000000000000001, 0x0000000000000000
Exception Note:        EXC_CORPSE_NOTIFY

Termination Signal:    Illegal instruction: 4
Termination Reason:    Namespace SIGNAL, Code 0x4
Terminating Process:   exc handler [79055]

Thread 0 Crashed:
0   com.apple.AppKit                0x00007fff30cc820a -[NSResponder _tryRetain] + 92
1   libobjc.A.dylib                 0x00007fff693a1e1d objc_loadWeakRetained + 351
2   libobjc.A.dylib                 0x00007fff693a3adc objc_loadWeak + 15
3   com.apple.AppKit                0x00007fff3075605a -[NSTableRowData ensureGroupRowIndexes] + 256
4   com.apple.AppKit                0x00007fff306e8161 -[NSTableView _isGroupRow:] + 106
5   com.apple.AppKit                0x00007fff30807219 -[NSTableView _sendDelegateHeightOfRow:] + 144
6   com.apple.AppKit                0x00007fff307f01cb -[NSTableView _safeSendDelegateHeightOfRow:] + 79
7   com.apple.AppKit                0x00007fff307f00f7 -[NSTableView _uncachedRectHeightOfRow:] + 274
8   com.apple.AppKit                0x00007fff307efe8c -[_NSTableRowHeightStorage _cacheRowHeights] + 52
9   com.apple.AppKit                0x00007fff3068a77d -[_NSTableRowHeightStorage _ensureRowHeights] + 57
10  com.apple.AppKit                0x00007fff3068a6cf -[_NSTableRowHeightStorage computeTableHeightForNumberOfRows:] + 80
11  com.apple.AppKit                0x00007fff30689b93 -[NSTableView _minimumFrameSize] + 73
12  com.apple.AppKit                0x00007fff3068918c -[NSTableView tile] + 285
13  com.apple.AppKit                0x00007fff306b014e -[NSTableView bounds] + 100
14  com.apple.AppKit                0x00007fff3065d920 -[NSView(NSInternal) _setLayerNeedsDisplayInViewRect:] + 171
15  com.apple.AppKit                0x00007fff306136b5 -[NSView setNeedsDisplayInRect:] + 767
16  com.apple.AppKit                0x00007fff30682a18 -[NSTableView _tileAndRedisplayAll] + 217
17  com.apple.CoreFoundation        0x00007fff3342c35f __CFNOTIFICATIONCENTER_IS_CALLING_OUT_TO_AN_OBSERVER__ + 12
18  com.apple.CoreFoundation        0x00007fff334bcc73 ___CFXRegistrationPost1_block_invoke + 63
19  com.apple.CoreFoundation        0x00007fff334bc308 _CFXRegistrationPost1 + 372
20  com.apple.CoreFoundation        0x00007fff334349be ___CFXNotificationPost_block_invoke + 97
21  com.apple.CoreFoundation        0x00007fff3339cce2 -[_CFXNotificationRegistrar find:object:observer:enumerator:] + 1575
22  com.apple.CoreFoundation        0x00007fff3339c172 _CFXNotificationPost + 1351
23  com.apple.Foundation            0x00007fff35a6336b -[NSNotificationCenter postNotificationName:object:userInfo:] + 59
My App Code

还有这个(来自另一个用户):

Crashed Thread:        0  Dispatch queue: com.apple.main-thread

Exception Type:        EXC_BAD_INSTRUCTION (SIGILL)
Exception Codes:       0x0000000000000001, 0x0000000000000000
Exception Note:        EXC_CORPSE_NOTIFY

Termination Signal:    Illegal instruction: 4
Termination Reason:    Namespace SIGNAL, Code 0x4
Terminating Process:   exc handler [68319]

Application Specific Information:
Refcount overflow in NSResponder or subclass. Too many unbalanced -retains!

Thread 0 Crashed:: Dispatch queue: com.apple.main-thread
0   com.apple.AppKit                0x00007fff3a50820a -[NSResponder _tryRetain] + 92
1   libobjc.A.dylib                 0x00007fff72d7ae1d objc_loadWeakRetained + 351
2   libobjc.A.dylib                 0x00007fff72d7cadc objc_loadWeak + 15
3   com.apple.AppKit                0x00007fff39fa1f0b -[NSTableRowData rowViewAtRow:createIfNeeded:] + 47
4   com.apple.AppKit                0x00007fff3a05577b -[NSTableView viewAtColumn:row:makeIfNecessary:] + 29
    My App Code

下面的留言一看吓到我

Application Specific Information: Refcount overflow in NSResponder or subclass. Too many unbalanced -retains!

最后,我确实设法将崩溃重现到测试项目中:

@implementation AppDelegate

NSString * const SIFTFilePresentationViewIdentifier = @"sift:file presentation";

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
    [self registerCells];// < - - - Commenting only this line fixes the issue.

    self.outlineView.delegate = self;
    self.outlineView.dataSource = self;
}

- (void)registerCells {
    NSNib *nib = [[NSNib alloc] initWithNibNamed:@"SIFTFileView" bundle:nil];
    [self.outlineView registerNib:nib forIdentifier:SIFTFilePresentationViewIdentifier];
}

- (NSInteger)outlineView:(NSOutlineView *)outlineView numberOfChildrenOfItem:(id)item {
    if (item == nil) {
        //Works fine:
        //10.14.5 (18F132)
        //MacBook Pro (15-inch, 2017)

        //Crashes:
        //10.15.1 (19B88)
        //MacBook Pro (15-inch, 2018)

        //2^25 = 33554432
        return 33560000;
    } else {
        return 0;
    }
}

- (id)outlineView:(NSOutlineView *)outlineView child:(NSInteger)index ofItem:(id)item {
    if (item == nil) {
        return @"321";
    } else {
        return nil;
    }
}

- (BOOL)outlineView:(NSOutlineView *)outlineView isItemExpandable:(id)item {
    return item == nil;
}

- (BOOL)outlineView:(NSOutlineView *)outlineView isGroupItem:(id)item {// < - - - Commenting only this method fixes the issue.
    return item == nil;
}

@end

项目重现问题: https://github.com/Vladimir-Nn/NSTableViewRefcountOverflow

网上的一些相关讨论:

NSParagraphStyle had a 19-bit inline retain count with no overflow protection (i.e. it incorrectly deallocated if you retained it too much and then called some releases). This occasionally crashed in Xcode (rdar://16008112).

https://forums.swift.org/t/shrinking-the-heap-object-header/1078

I can't really see any memory management going on in the LWJGL code that would cause the overflow. Therefore the crash appears to be originating from inside the firstResponder method. If it doesn't happen in previous versions of MacOS, I'm guessing its probably an OS bug or some sort of change in behaviour in how that method worked.

http://forum.lwjgl.org/index.php?topic=6951.msg36545#msg36545

I don't immediately understand why this would be crashing, we're just asking an NSTextView to scroll itself.

I did notice in the crash report that there's an info text of Refcount overflow in NSResponder or subclass. Too many unbalanced -retains! - @asmagill do you think that this block should be working from a weak reference to self? I'm struggling to imagine it's important, since we log a lot of stuff, all the time and I don't believe we've ever seen this crash before.

https://github.com/Hammerspoon/hammerspoon/issues/2206

OS 版本:Mac OS X 10.15.1 (19B88)

我认为这是 NSTableView 的内部错误。如果您有任何想法,请告诉我。

我认为这是 NSTableView 内部错误。

就我而言,仅评论以下方法即可解决问题。

- (BOOL)outlineView:(NSOutlineView *)outlineView isGroupItem:(id)item {
    return item == nil;
}

因此,我使用 outlineView:isGroupItem: 方法和不使用方法为 NSTableViewDelegate 创建了 2 个对象。我刚刚代理给 "previous" 委托的所有其他呼叫。

- (void)updateInterfaceOfOutlineView {
    NSOutlineView *outlineView = self.outlineView;
    for (NSUInteger rowIndex = 0; rowIndex < outlineView.numberOfRows; rowIndex++) {
        @autoreleasepool {//Adding this autoreleasepool also increased the amount of possible rows in table.
            NSView *itemView = [outlineView viewAtColumn:0 row:rowIndex makeIfNecessary:NO];
            if(itemView && [itemView respondsToSelector:@selector(updateInterface)]) {
                [(id<SelectedItemView>)itemView updateInterface];
            }
        }
    }
}

遗留代码...不要对它过分挑剔。