代码调试基础:如何看懂调用栈和栈帧信息
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) 命令输出的调用栈信息的格式为【栈帧序号-内存地址-函数名-偏移量】,其中偏移量是该函数相对于该函数所在栈帧内存开始的偏移量(十进制)。