Objective c 自旋转储分析说明?

Objective c 自旋转储分析说明?,objective-c,xcode,macos,Objective C,Xcode,Macos,我收集了一些关于需要分析的应用程序的旋转转储,但是我不确定如何准确地分析这些。我见过一些其他的开发人员,他们能够快速地从思想上或软件上解析这些内容,然后回来告诉我挂起的细节等等,我希望了解如何正确地分析这些内容 在哪里可以正确分析spindump?我在Mac开发者资源中搜索“spindump”时发现了这个问题。 我从未见过,但ReportCrash(8)手册页面中提到的这个技术说明似乎向您展示了如何阅读崩溃日志: 我很抱歉,ReportCrash(8)提到了Spindump(8)。 但显然这

我收集了一些关于需要分析的应用程序的旋转转储,但是我不确定如何准确地分析这些。我见过一些其他的开发人员,他们能够快速地从思想上或软件上解析这些内容,然后回来告诉我挂起的细节等等,我希望了解如何正确地分析这些内容


在哪里可以正确分析spindump?

我在Mac开发者资源中搜索“spindump”时发现了这个问题。 我从未见过,但ReportCrash(8)手册页面中提到的这个技术说明似乎向您展示了如何阅读崩溃日志:

我很抱歉,ReportCrash(8)提到了Spindump(8)。

但显然这对你没有帮助。我也会把它留在这里

希望这能帮助别人解决问题。

一般来说:

  • 通过崩溃报告,您可以得到堆栈跟踪
  • 使用自旋转储,您可以在一段时间内同时获得多个堆栈跟踪
有两种情况可能需要检查spindump:

  • 一个无限循环,可能反复调用同一个函数
  • 僵局
  • 第一种情况可以通过多次调用同一个函数从spindump中看到。在这种情况下使用的一个好方法是活动监视器——在那里对挂起的进程进行采样,您可以用几种有用的方式查看它,隐藏不重要的帧,等等

    第二种情况可以由同时等待锁的不同线程查看

    下面是一个小例子:

    + 2663 start  (in MyApp) + 52  [0x100001bb4]
    +   2663 main  (in MyApp) + 39  [0x100001be7]  main.m:65
    +     2663 NSApplicationMain  (in AppKit) + 869  [0x7fff8ea27cb6]
    +       2663 -[NSApplication run]  (in AppKit) + 517  [0x7fff8ea83283]
    +         2663 -[NSApplication nextEventMatchingMask:untilDate:inMode:dequeue:]  (in AppKit) + 128  [0x7fff8ea8bed2]
    +           2663 _DPSNextEvent  (in AppKit) + 685  [0x7fff8ea8c613]
    +             2663 BlockUntilNextEventMatchingListInMode  (in HIToolbox) + 62  [0x7fff8dd53cd3]
    +               2663 ReceiveNextEventCommon  (in HIToolbox) + 356  [0x7fff8dd53e42]
    +                 2663 RunCurrentEventLoopInMode  (in HIToolbox) + 209  [0x7fff8dd540a4]
    +                   2663 CFRunLoopRunSpecific  (in CoreFoundation) + 290  [0x7fff95dec6b2]
    +                     2557 __CFRunLoopRun  (in CoreFoundation) + 1078  [0x7fff95decee6]
    +                     ! 2556 __CFRunLoopServiceMachPort  (in CoreFoundation) + 195  [0x7fff95de7803]
    +                     ! : 2556 mach_msg  (in libsystem_kernel.dylib) + 70  [0x7fff93630c42]
    +                     ! :   2556 mach_msg_trap  (in libsystem_kernel.dylib) + 10  [0x7fff93631686]
    +                     ! 1 __CFRunLoopServiceMachPort  (in CoreFoundation) + 199  [0x7fff95de7807]
    +                     97 __CFRunLoopRun  (in CoreFoundation) + 728  [0x7fff95decd88]
    +                     ! 97 __CFRunLoopDoObservers  (in CoreFoundation) + 369  [0x7fff95e11921]
    +                     !   97 __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__  (in CoreFoundation) + 23  [0x7fff95e119b7]
    +                     !     97 __83-[NSWindow _postWindowNeedsDisplayOrLayoutOrUpdateConstraintsUnlessPostingDisabled]_block_invoke_01208  (in AppKit) + 46  [0x7fff8f05a971]
    +                     !       90 _handleWindowNeedsDisplayOrLayoutOrUpdateConstraints  (in AppKit) + 738  [0x7fff8ea8f2ac]
    +                     !       : 89 -[NSView displayIfNeeded]  (in AppKit) + 1830  [0x7fff8ea8fd73]
    
    这告诉我,我的应用程序已经通过main等,最终进入了一个函数
    CFRunLoopRunSpecific
    ,然后
    \uuucfrunlooprun
    ——从那里(2557)它调用了
    \ucfrunloopservicemachport
    ,它调用了
    mach\u msg
    ,并在
    mach\u msg\u trap
    进入了一个陷阱(调用系统调用)–当它返回时,堆栈跟踪返回到
    CFRunLoopRunSpecific
    ,其中调用了
    \uu CFRunLoopRun
    ,然后调用
    \uu cfrunloopdoobserver
    ,依此类推

    请注意,这不是任何挂起进程的spindump-您可以通过这种方式对任何正在运行的进程进行采样,并查看在该采样期间调用了哪些函数。然而,一个无限循环会一次又一次地重复对某个函数的调用——会一次又一次地出现相同的调用树。当然,这可能意味着一个简单的for循环,但如果for循环由于某种原因不是无限的,那么您可以在这里进行检查。不幸的是,这些自旋转储通常相当长,这取决于您调用的函数,因此可能需要一些时间来检查

    行开头的+号表示行的开始-没有+号的行表示新线程的开始。这个和:符号构成一条线,因此您更容易看到后续呼叫,即哪些呼叫处于同一级别。此外,还可以使用|字符


    这些数字表示应用程序在该特定呼叫中花费的时间-它们包含在样本数中。采样的工作原理是每几毫秒就暂停一次采样的应用程序,并检查每个线程的堆栈帧。如果应用程序仍在同一个功能中,则该功能将得到+1。

    –Google Groups视图。我不是开发人员,但我经常看到像我这样的人对spindump分析感到好奇–因此最近的悬赏。这对崩溃很有用,但对spindump没有帮助。苹果没有提到ReportCrash(8)。而且,spindump页面只描述了手动触发采样的实用程序,而没有描述输出。如何解释每行的数字标题?表示(+、!、:)的符号是什么?是否没有软件机制可以让您传递这些信息,从而帮助您更有意义地解析这些信息?我主要处理奇怪的挂起,并试图找出这些挂起的来源。这是非常有价值的理解尽可能密切,但目前考虑到时间的差异,我有点脱离上下文。举个例子,你的回答很有道理;我觉得当我再次遇到这个问题时,仍然缺少一个正确解释这些问题的部分。HMM对于没有软件开发背景的读者:请问,这是一个无限循环的例子,还是死锁?加号表示一行的开始-没有加号的行表示一个新线程的开始。这个而且:符号只是排成一条线,所以你更容易看到后续的呼叫,也就是说,哪些呼叫处于同一级别。此外,还可以使用|字符。这些数字表示应用程序在该特定呼叫中花费的时间(可能以毫秒为单位),但这并不重要。上面的示例根本不是挂起的应用程序,你可以通过运行应用程序来了解它们的工作方式。然而,一个无限循环会一次又一次地重复对某个函数的调用——会一次又一次地出现相同的调用树。当然,这可能意味着一个简单的for循环,但如果for循环由于某种原因不是无限的,那么您可以在这里进行检查。不幸的是,这些自旋转储通常相当长,这取决于您调用的函数,因此可能需要一些时间来检查。好的,现在有了这个澄清,我投了赞成票@CharlieMonroe可能会将这篇评论编辑成你的答案,如果它没有改变本质的话——谢谢。