更新到 macOS Mojave 后 [NSWindow orderFrontRegardless] 崩溃
Crash in [NSWindow orderFrontRegardless] after updating to macOS Mojave
更新到 Mojave 后出现奇怪的崩溃。
没有做任何特别的事情,只是创建一个 NSWindow 并调用 orderFrontRegardless
之前一直很好用。
1 libsystem_platform.dylib 0x00007fff6610ab5d _sigtramp + 29
2 ??? 0x0000000000000000 0x0 + 0
3 CoreFoundation 0x00007fff39b00bb6 __CFNOTIFICATIONCENTER_IS_CALLING_OUT_TO_AN_OBSERVER__ + 12
4 CoreFoundation 0x00007fff39b00b30 ___CFXRegistrationPost_block_invoke + 63
5 CoreFoundation 0x00007fff39b00a9a _CFXRegistrationPost + 404
6 CoreFoundation 0x00007fff39b08f48 ___CFXNotificationPost_block_invoke + 87
7 CoreFoundation 0x00007fff39a71994 -[_CFXNotificationRegistrar find:object:observer:enumerator:] + 1642
8 CoreFoundation 0x00007fff39a70d47 _CFXNotificationPost + 732
9 Foundation 0x00007fff3bdab217 -[NSNotificationCenter postNotificationName:object:userInfo:] + 66
10 AppKit 0x00007fff3720538b -[NSWindow _setFrameCommon:display:stashSize:] + 3090
11 AppKit 0x00007fff37204766 -[NSWindow _setFrame:display:allowImplicitAnimation:stashSize:] + 192
12 AppKit 0x00007fff3720469f -[NSWindow setFrame:display:] + 51
13 AppKit 0x00007fff3727aca9 -[NSWindow _reallyDoOrderWindowAboveOrBelow:relativeTo:findKey:forCounter:force:isModal:] + 1336
14 AppKit 0x00007fff372792a0 -[NSWindow _doOrderWindow:relativeTo:findKey:forCounter:force:isModal:] + 283
15 AppKit 0x00007fff37a0dce9 -[NSWindow orderFrontRegardless] + 40
代码(这是一个控制台应用程序):
NSWindow *window = [[NSWindow alloc] initWithContentRect:windowRect
styleMask:windowStyle
backing:NSBackingStoreBuffered
defer:NO];
// Since Snow Leopard, programs without application bundles and Info.plist
// files don't get a menubar and can't be brought to the front unless the
// presentation option is changed
[NSApp setActivationPolicy:NSApplicationActivationPolicyRegular];
[NSApp activateIgnoringOtherApps:YES];
[window makeKeyAndOrderFront:nil];
如何初始化应用程序?在使用 AppKit
之前,您是否已初始化 NSApplication
?
在 main.m:
中应该需要类似这些步骤
@autoreleasepool {
NSApplication* application = NSApplication.sharedApplication;
AppDelegate* delegate = [[AppDelegate alloc] init];
application.delegate = delegate;
[application run];
}
您的委托也可能会被释放,因为 NSApp
持有对它的弱引用。
原来我在一个完全不同的地方有一个严重的内存错误,甚至在回溯中都没有提到。
我正在取消引用一个未初始化的指针。
这是第二次了。
调试内存错误时不要相信 Apple 的回溯。
即使使用 libgmalloc。
您表示您正在取消引用未初始化的指针。但是,我没有从您发布的报告中获得足够的信息来知道这是否(也许是运气)为空,或者只是垃圾内存。我假设在某个时候你因 EXC_BAD_ACCESS
而崩溃(等效信号为 SIGBUS
或 SIGSEGV
,视情况而定)。
这里的关键一点信息是您安装了信号处理程序。
信号处理程序通常(但不总是)运行 在崩溃线程上使用相同的堆栈。内核使用 _sigtramp
函数注入处理程序。信号传递后,当前堆栈状态包含您追踪不良内存访问所需的信息。但是,您的信号处理程序被调用了。所以它 运行,像它那样改变堆栈。
然后,您的信号处理程序以某种方式完成。可以使用 sigaction
配置信号处理程序,以便将进程状态恢复到崩溃事件之前的那一刻。我不确定您的信号处理程序是如何配置的。但是,最终,我将假设允许该进程退出。
此时,Apple 的 ReportCrash 将被触发,并将捕获所有线程的回溯无论您的信号处理程序离开它们的状态如何。这很关键,因为那不一定是崩溃状态。
增加了复杂性,backtrace_symbols_fd
从信号处理程序中使用一点也不安全。异步安全具有挑战性,来自信号处理程序的 运行ning 代码非常 难以正确处理。您可以安全地做的事情很少。此外,我很确定 backtrace_symbols_fd
分配内存。所以,如果你的崩溃发生在内存分配器的某个地方,而且听起来确实如此,那么你肯定有死锁的风险。从回溯来看,这似乎正是可能发生的事情。查看 man sigaction
了解一些详细信息。
更糟糕的是,在信号处理程序框架上展开堆栈特别具有挑战性,因为内核对 运行 您的处理程序具有魔力。这就是 ???
框架在那里的原因。
总结:
如果没有安装信号处理程序,Apple 的 ReportCrash 会为崩溃的线程生成正确(并且可能有用)的回溯。
您包含的堆栈跟踪不是很好,但很难确切知道原因。
backtrace_symbols_fd
似乎没有很好地展开,可能是因为它不适合从信号处理程序使用,也可能是因为它没有足够好的堆栈展开机制支持这种情况。但是,没有更多信息,我很难知道。不过,令我惊讶的是,顶部框架是 _sigtramp
。这没有多大意义。这让我觉得信号处理程序本身可能出了问题。 可能会在您的处理程序中第二次崩溃。
Apple 的回溯(例如,由 ReportCrash backtrace_symbols_fd
或 NSThread 的 callStackReturnAddresses
生成)绝对值得信赖,前提是您在安全的上下文中小心使用它们。
更新到 Mojave 后出现奇怪的崩溃。
没有做任何特别的事情,只是创建一个 NSWindow 并调用 orderFrontRegardless
之前一直很好用。
1 libsystem_platform.dylib 0x00007fff6610ab5d _sigtramp + 29
2 ??? 0x0000000000000000 0x0 + 0
3 CoreFoundation 0x00007fff39b00bb6 __CFNOTIFICATIONCENTER_IS_CALLING_OUT_TO_AN_OBSERVER__ + 12
4 CoreFoundation 0x00007fff39b00b30 ___CFXRegistrationPost_block_invoke + 63
5 CoreFoundation 0x00007fff39b00a9a _CFXRegistrationPost + 404
6 CoreFoundation 0x00007fff39b08f48 ___CFXNotificationPost_block_invoke + 87
7 CoreFoundation 0x00007fff39a71994 -[_CFXNotificationRegistrar find:object:observer:enumerator:] + 1642
8 CoreFoundation 0x00007fff39a70d47 _CFXNotificationPost + 732
9 Foundation 0x00007fff3bdab217 -[NSNotificationCenter postNotificationName:object:userInfo:] + 66
10 AppKit 0x00007fff3720538b -[NSWindow _setFrameCommon:display:stashSize:] + 3090
11 AppKit 0x00007fff37204766 -[NSWindow _setFrame:display:allowImplicitAnimation:stashSize:] + 192
12 AppKit 0x00007fff3720469f -[NSWindow setFrame:display:] + 51
13 AppKit 0x00007fff3727aca9 -[NSWindow _reallyDoOrderWindowAboveOrBelow:relativeTo:findKey:forCounter:force:isModal:] + 1336
14 AppKit 0x00007fff372792a0 -[NSWindow _doOrderWindow:relativeTo:findKey:forCounter:force:isModal:] + 283
15 AppKit 0x00007fff37a0dce9 -[NSWindow orderFrontRegardless] + 40
代码(这是一个控制台应用程序):
NSWindow *window = [[NSWindow alloc] initWithContentRect:windowRect
styleMask:windowStyle
backing:NSBackingStoreBuffered
defer:NO];
// Since Snow Leopard, programs without application bundles and Info.plist
// files don't get a menubar and can't be brought to the front unless the
// presentation option is changed
[NSApp setActivationPolicy:NSApplicationActivationPolicyRegular];
[NSApp activateIgnoringOtherApps:YES];
[window makeKeyAndOrderFront:nil];
如何初始化应用程序?在使用 AppKit
之前,您是否已初始化 NSApplication
?
在 main.m:
中应该需要类似这些步骤@autoreleasepool {
NSApplication* application = NSApplication.sharedApplication;
AppDelegate* delegate = [[AppDelegate alloc] init];
application.delegate = delegate;
[application run];
}
您的委托也可能会被释放,因为 NSApp
持有对它的弱引用。
原来我在一个完全不同的地方有一个严重的内存错误,甚至在回溯中都没有提到。
我正在取消引用一个未初始化的指针。
这是第二次了。
调试内存错误时不要相信 Apple 的回溯。
即使使用 libgmalloc。
您表示您正在取消引用未初始化的指针。但是,我没有从您发布的报告中获得足够的信息来知道这是否(也许是运气)为空,或者只是垃圾内存。我假设在某个时候你因 EXC_BAD_ACCESS
而崩溃(等效信号为 SIGBUS
或 SIGSEGV
,视情况而定)。
这里的关键一点信息是您安装了信号处理程序。
信号处理程序通常(但不总是)运行 在崩溃线程上使用相同的堆栈。内核使用 _sigtramp
函数注入处理程序。信号传递后,当前堆栈状态包含您追踪不良内存访问所需的信息。但是,您的信号处理程序被调用了。所以它 运行,像它那样改变堆栈。
然后,您的信号处理程序以某种方式完成。可以使用 sigaction
配置信号处理程序,以便将进程状态恢复到崩溃事件之前的那一刻。我不确定您的信号处理程序是如何配置的。但是,最终,我将假设允许该进程退出。
此时,Apple 的 ReportCrash 将被触发,并将捕获所有线程的回溯无论您的信号处理程序离开它们的状态如何。这很关键,因为那不一定是崩溃状态。
增加了复杂性,backtrace_symbols_fd
从信号处理程序中使用一点也不安全。异步安全具有挑战性,来自信号处理程序的 运行ning 代码非常 难以正确处理。您可以安全地做的事情很少。此外,我很确定 backtrace_symbols_fd
分配内存。所以,如果你的崩溃发生在内存分配器的某个地方,而且听起来确实如此,那么你肯定有死锁的风险。从回溯来看,这似乎正是可能发生的事情。查看 man sigaction
了解一些详细信息。
更糟糕的是,在信号处理程序框架上展开堆栈特别具有挑战性,因为内核对 运行 您的处理程序具有魔力。这就是 ???
框架在那里的原因。
总结:
如果没有安装信号处理程序,Apple 的 ReportCrash 会为崩溃的线程生成正确(并且可能有用)的回溯。
您包含的堆栈跟踪不是很好,但很难确切知道原因。
backtrace_symbols_fd
似乎没有很好地展开,可能是因为它不适合从信号处理程序使用,也可能是因为它没有足够好的堆栈展开机制支持这种情况。但是,没有更多信息,我很难知道。不过,令我惊讶的是,顶部框架是 _sigtramp
。这没有多大意义。这让我觉得信号处理程序本身可能出了问题。 可能会在您的处理程序中第二次崩溃。
Apple 的回溯(例如,由 ReportCrash backtrace_symbols_fd
或 NSThread 的 callStackReturnAddresses
生成)绝对值得信赖,前提是您在安全的上下文中小心使用它们。