【问题标题】:Crash in [NSWindow orderFrontRegardless] after updating to macOS Mojave更新到 macOS Mojave 后 [NSWindow orderFrontRegardless] 崩溃
【发布时间】:2019-07-12 06:47:21
【问题描述】:

更新到 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];

【问题讨论】:

  • 可能会向已释放/已死的对象发送通知。你有最低限度的代码示例吗?
  • @WarrenBurton 我已经添加了代码。
  • 评论是否相关?即这个应用程序没有 plist 和 bundle 吗? .我无法在常规基线“Cocoa App”模板中重现崩溃。
  • 是的,它是一个控制台应用程序。
  • _sigtramp 的最后一个堆栈帧表明您安装了信号处理程序 - 可能是第 3 方崩溃报告器。这个堆栈跟踪实际上是从哪里来的?这些通常会与 Apple 的 ReportCrash 混淆,因此无法捕获原始的崩溃堆栈跟踪。

标签: objective-c macos cocoa crash macos-mojave


【解决方案1】:

如何初始化应用程序?在使用AppKit 之前,您是否已初始化NSApplication

在 main.m 中应该需要类似这些步骤:

@autoreleasepool {
    NSApplication* application = NSApplication.sharedApplication;

    AppDelegate* delegate = [[AppDelegate alloc] init];
    application.delegate = delegate;

    [application run];
}

您的委托也可能被解除分配,因为 NSApp 持有对它的弱引用。

【讨论】:

  • 谢谢,我尝试了@autorelease 池,仍然有 10% 的用户崩溃。我认为某个地方存在内存错误,将在 Linux 上使用 Valgrind 对其进行调试。
【解决方案2】:

您表示您正在取消引用未初始化的指针。但是,我没有从您发布的报告中获得足够的信息来知道这是否(可能是运气)为空,或者只是垃圾内存。我假设您在某个时候因EXC_BAD_ACCESS 而崩溃(信号等效为SIGBUSSIGSEGV,具体取决于)。

这里的关键信息是您安装了信号处理程序。

信号处理程序通常(但不总是)使用相同的堆栈在崩溃线程上运行。内核使用_sigtramp 函数注入处理程序。信号传递后,当前堆栈状态包含跟踪不良内存访问所需的信息。但是,您的信号处理程序被调用了。所以它运行,改变堆栈。

然后,您的信号处理程序以某种方式完成。可以使用sigaction 配置信号处理程序,以便将进程状态恢复到崩溃事件之前的时刻。我不确定您的信号处理程序是如何配置的。但是,最终,我将假设该进程被允许退出。

此时,Apple 的 ReportCrash 将被触发,并将捕获所有线程的回溯在您的信号处理程序离开它们的任何状态。这很关键,因为这不一定是崩溃状态。

增加了复杂性,backtrace_symbols_fd根本不安全从信号处理程序中使用。异步安全具有挑战性,并且从信号处理程序运行代码非常很难做到正确。您可以安全地做的事情很少。此外,我很确定 backtrace_symbols_fd 分配内存。因此,如果您的崩溃发生在某处的内存分配器中,并且听起来确实如此,那么您肯定会面临死锁的风险。从回溯来看,这似乎正是可能发生的事情。详情请查看man sigaction

更糟糕的是,在信号处理程序帧上展开堆栈特别具有挑战性,因为内核在运行您的处理程序时具有魔力。这就是??? 框架存在的原因。

总结:

如果没有安装信号处理程序,Apple 的 ReportCrash 会为崩溃线程生成正确的(并且可能有用的)回溯。

您包含的堆栈跟踪不是很好,但很难确切知道原因。 backtrace_symbols_fd 似乎没有很好地展开,可能是因为它不适合从信号处理程序中使用,可能是因为它没有得到足够好的堆栈展开机制来支持这种情况。但是,没有更多信息,我很难知道。不过,我很惊讶顶部框架是_sigtramp。这没有多大意义。这让我觉得信号处理程序本身可能出了问题。 有可能在您的处理程序中再次崩溃。

Apple 的回溯(例如,由 ReportCrash、backtrace_symbols_fd 或 NSThread 的 callStackReturnAddresses 生成)绝对可以信任,只要您在安全的环境中小心使用它们。

【讨论】:

  • 这非常有用。非常感谢您花时间。这是一个指向垃圾的未初始化指针,因为我有一个 != NULL 检查,但它没有帮助。我正在用我自己的编译为 C 的语言开发这个应用程序,并且我已经为每个字段添加了自动指针初始化,以防止这种情况再次发生 :)
  • 从现在开始,我将避免从 sig 处理程序调用 backtrace_symbols_fd
  • 不客气!项目听起来很酷,我明白你为什么
  • 不客气!项目听起来很酷,我理解你为什么想要这个。可以在信号处理程序中进行堆栈展开,这只是更多的手动工作 - 特别是在 macOS 上。
【解决方案3】:

原来我在一个完全不同的地方有一个严重的内存错误,甚至没有在回溯中提到。

我正在取消引用一个未初始化的指针。

这是第二次了。

在调试内存错误时不要相信 Apple 的回溯。

即使使用 libgmalloc。

【讨论】:

  • 我发布了一个希望有用的答案。我敢打赌,如果您在没有信号处理程序的情况下重现此崩溃,您会发现从调试器或 ReportCrash(Apple 的自动崩溃报告机制)获得的回溯会更有帮助。
猜你喜欢
  • 1970-01-01
  • 2019-03-02
  • 1970-01-01
  • 2019-05-12
  • 2019-03-07
  • 2019-03-10
  • 1970-01-01
  • 2019-03-16
  • 1970-01-01
相关资源
最近更新 更多