代码调试基础:如何看懂调用栈和栈帧信息 
    
      
        2024.03.01 
       
      
        
          Niyao 
         
      
      
      
      
      
            热度 
            ℃
         
      
      
    
   
  
    
      调用栈 (Call Stack) 和栈帧 (Stack Frame) 
调用栈 (Call Stack) 
In computer science, a call stack is a stack data structure that stores information about the active subroutines of a computer program. This type of stack is also known as an execution stack, program stack, control stack, run-time stack, or machine stack, and is often shortened to simply “the stack”.
 
在计算机学中,调用栈(港台称「呼叫堆叠」)是指,一个存储计算机程序有关活跃子事务的栈数据结构。栈类型也同样被作为执行栈、程序栈、控制栈、运行时栈或者机器栈,并且经常简称为“栈”。
栈帧 (Stack Frame) 
In computer science, a stack frame is a memory management strategy used to create and destroy temporary (automatic) variables in procedural programming languages. Among other things, use of a stack allows programming languages to allow recursive calling of subroutines. Stack frames only exist at run-time.
 
在计算机学中,一个栈帧是一个程序上用于创建和销毁临时(自动)变量的内存管理策略。在其他事务中,一个栈允许编程语言,以用于子事务的递归调用。栈帧仅在运行时退出。
示例 
审查 SwiftUI 项目的 Call Stack 和 Stack Frame 
用 Xcode 创建一个 SwiftUI 项目,在 contentView 函数后设置断点,程序运行后在 console 中输入 bt(backtrace) 查看详细的调用栈。通常在 Xcode 左边 「Show the Debug navigator」中的线程调用栈只是部分调用栈,会隐藏未开源码的相关栈帧。
* thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 2.1   * frame #0: 0x000000010202aea0 SwiftUIDemo`closure #1 in SwiftUIDemoApp.body.getter at SwiftUIDemoApp.swift:15:18     frame #1: 0x00000001c494a65c SwiftUI`SwiftUI.WindowGroup.init(content: () -> τ_0_0) -> SwiftUI.WindowGroup<τ_0_0> + 96     frame #2: 0x000000010202ade0 SwiftUIDemo`SwiftUIDemoApp.body.getter(self=SwiftUIDemo.SwiftUIDemoApp @ scalar) at SwiftUIDemoApp.swift:13:9     frame #3: 0x000000010202b088 SwiftUIDemo`protocol witness for App.body.getter in conformance SwiftUIDemoApp at <compiler-generated>:0     frame #4: 0x00000001c5aa9b4c SwiftUI`___lldb_unnamed_symbol275986 + 1364     frame #5: 0x00000001c586bec4 SwiftUI`___lldb_unnamed_symbol256724 + 300     frame #6: 0x00000001c586bc38 SwiftUI`___lldb_unnamed_symbol256723 + 204     frame #7: 0x00000001c5374abc SwiftUI`___lldb_unnamed_symbol216776 + 28     frame #8: 0x00000001b2bdc75c AttributeGraph`AG::Graph::UpdateStack::update() + 504     frame #9: 0x00000001b2bdceec AttributeGraph`AG::Graph::update_attribute(AG::data::ptr<AG::Node>, unsigned int) + 432     frame #10: 0x00000001b2be4e90 AttributeGraph`AG::Graph::input_value_ref_slow(AG::data::ptr<AG::Node>, AG::AttributeID, unsigned int, unsigned int, AGSwiftMetadata const*, unsigned char&, long) + 716     frame #11: 0x00000001b2bfbd24 AttributeGraph`AGGraphGetValue + 232     frame #12: 0x00000001c586bb1c SwiftUI`___lldb_unnamed_symbol256721 + 80     frame #13: 0x00000001c586be98 SwiftUI`___lldb_unnamed_symbol256724 + 256     frame #14: 0x00000001c586bc38 SwiftUI`___lldb_unnamed_symbol256723 + 204     frame #15: 0x00000001c5374abc SwiftUI`___lldb_unnamed_symbol216776 + 28     frame #16: 0x00000001b2bdc75c AttributeGraph`AG::Graph::UpdateStack::update() + 504     frame #17: 0x00000001b2bdceec AttributeGraph`AG::Graph::update_attribute(AG::data::ptr<AG::Node>, unsigned int) + 432     frame #18: 0x00000001b2be4e90 AttributeGraph`AG::Graph::input_value_ref_slow(AG::data::ptr<AG::Node>, AG::AttributeID, unsigned int, unsigned int, AGSwiftMetadata const*, unsigned char&, long) + 716     frame #19: 0x00000001b2bfbd24 AttributeGraph`AGGraphGetValue + 232     frame #20: 0x00000001c494b3ec SwiftUI`___lldb_unnamed_symbol138618 + 64     frame #21: 0x00000001c494b4dc SwiftUI`___lldb_unnamed_symbol138620 + 152     frame #22: 0x00000001c5374abc SwiftUI`___lldb_unnamed_symbol216776 + 28     frame #23: 0x00000001b2bdc75c AttributeGraph`AG::Graph::UpdateStack::update() + 504     frame #24: 0x00000001b2bdceec AttributeGraph`AG::Graph::update_attribute(AG::data::ptr<AG::Node>, unsigned int) + 432     frame #25: 0x00000001b2be44ec AttributeGraph`AG::Graph::value_ref(AG::AttributeID, unsigned int, AGSwiftMetadata const*, unsigned char&) + 252     frame #26: 0x00000001b2bfbd70 AttributeGraph`AGGraphGetValue + 308     frame #27: 0x00000001c5aa8180 SwiftUI`___lldb_unnamed_symbol275929 + 60     frame #28: 0x00000001c49ae37c SwiftUI`___lldb_unnamed_symbol141796 + 176     frame #29: 0x00000001c49a9b50 SwiftUI`___lldb_unnamed_symbol141692 + 1144     frame #30: 0x00000001c49aaa88 SwiftUI`___lldb_unnamed_symbol141697 + 96     frame #31: 0x0000000184805e18 UIKitCore`+[UIScene _sceneForFBSScene:create:withSession:connectionOptions:] + 1012     frame #32: 0x00000001852f1644 UIKitCore`-[UIApplication _connectUISceneFromFBSScene:transitionContext:] + 804     frame #33: 0x00000001852f192c UIKitCore`-[UIApplication workspace:didCreateScene:withTransitionContext:completion:] + 356     frame #34: 0x0000000184de0cc4 UIKitCore`-[UIApplicationSceneClientAgent scene:didInitializeWithEvent:completion:] + 260     frame #35: 0x0000000186e03190 FrontBoardServices`-[FBSScene _callOutQueue_didCreateWithTransitionContext:completion:] + 296     frame #36: 0x0000000186e2c3d4 FrontBoardServices`__92-[FBSWorkspaceScenesClient createSceneWithIdentity:parameters:transitionContext:completion:]_block_invoke.82 + 224     frame #37: 0x0000000186e0fd6c FrontBoardServices`-[FBSWorkspace _calloutQueue_executeCalloutFromSource:withBlock:] + 160     frame #38: 0x0000000186e2c14c FrontBoardServices`__92-[FBSWorkspaceScenesClient createSceneWithIdentity:parameters:transitionContext:completion:]_block_invoke + 284     frame #39: 0x000000010216593c libdispatch.dylib`_dispatch_client_callout + 16     frame #40: 0x0000000102169534 libdispatch.dylib`_dispatch_block_invoke_direct + 392     frame #41: 0x0000000186e4fb24 FrontBoardServices`__FBSSERIALQUEUE_IS_CALLING_OUT_TO_A_BLOCK__ + 44     frame #42: 0x0000000186e4fa00 FrontBoardServices`-[FBSMainRunLoopSerialQueue _targetQueue_performNextIfPossible] + 196     frame #43: 0x0000000186e4fb58 FrontBoardServices`-[FBSMainRunLoopSerialQueue _performNextFromRunLoopSource] + 24     frame #44: 0x00000001803f1f18 CoreFoundation`__CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 24     frame #45: 0x00000001803f1e60 CoreFoundation`__CFRunLoopDoSource0 + 172     frame #46: 0x00000001803f1628 CoreFoundation`__CFRunLoopDoSources0 + 320     frame #47: 0x00000001803ebcb8 CoreFoundation`__CFRunLoopRun + 768     frame #48: 0x00000001803eb5a4 CoreFoundation`CFRunLoopRunSpecific + 572     frame #49: 0x000000018e9fbae4 GraphicsServices`GSEventRunModal + 160     frame #50: 0x00000001852f02e4 UIKitCore`-[UIApplication _run] + 868     frame #51: 0x00000001852f3f5c UIKitCore`UIApplicationMain + 124     frame #52: 0x00000001c51fc1b0 SwiftUI`___lldb_unnamed_symbol205407 + 172     frame #53: 0x00000001c51fc050 SwiftUI`___lldb_unnamed_symbol205405 + 140     frame #54: 0x00000001c4f02fa4 SwiftUI`static SwiftUI.App.main() -> () + 80     frame #55: 0x000000010202b000 SwiftUIDemo`static SwiftUIDemoApp.$main(self=SwiftUIDemo.SwiftUIDemoApp) at <compiler-generated>:0     frame #56: 0x000000010202b0b0 SwiftUIDemo`main at SwiftUIDemoApp.swift:11:8     frame #57: 0x0000000102735544 dyld_sim`start_sim + 20     frame #58: 0x0000000102236058 dyld`start + 2224 
backtrace (bt) 命令输出的调用栈信息的格式为【栈帧序号-内存地址-函数名-偏移量】,其中偏移量是该函数相对于该函数所在栈帧内存开始的偏移量(十进制)。