Objective-C 方法的执行会创建 "frames on the stack" 吗?
Does the execution of Objective-C methods create "frames on the stack"?
我知道,在 C 中,每个函数都会创建一个框架,并且当使用它的函数结束时,每个框架都会自动释放。同样的逻辑是否适用于 Objective-C 方法?它们在执行时会在堆栈上创建 帧 吗?
是的,他们有。
Objective-C 动态调用方法,所以:
[someObject doSomething];
相当于:
objc_msgSend(someObject, sel_registerName("doSomething"));
sel_registerName
returns 一个选择器,它基本上是给定方法名称的方法标识符。
objc_msgSend
是用汇编写的,代码可用here。它在对象的方法列表中查找选择器。方法列表包含选择器 doSomething
的 IMP
,它是指向类似于以下函数的 C 函数指针:
void doSomething(id self, SEL _cmd);
objc_msgSend
然后 tail-calls 函数指针,
所以方法只是常规的 C 函数,但它们在运行时动态调用。当调用 objc_msgSend
时,return 地址被压入堆栈,CPU 跳转到 objc_msgSend
。它看起来 objc_msgSend
根本没有触及堆栈,因此该方法就像 C 函数一样设置堆栈帧。完成后,该方法完全像 C 函数一样拆除它的堆栈框架和 returns。由于 objc_msgSend
未触及堆栈,因此它 return 直接转到调用方法的代码,就像直接调用方法实现一样。
我知道,在 C 中,每个函数都会创建一个框架,并且当使用它的函数结束时,每个框架都会自动释放。同样的逻辑是否适用于 Objective-C 方法?它们在执行时会在堆栈上创建 帧 吗?
是的,他们有。
Objective-C 动态调用方法,所以:
[someObject doSomething];
相当于:
objc_msgSend(someObject, sel_registerName("doSomething"));
sel_registerName
returns 一个选择器,它基本上是给定方法名称的方法标识符。
objc_msgSend
是用汇编写的,代码可用here。它在对象的方法列表中查找选择器。方法列表包含选择器 doSomething
的 IMP
,它是指向类似于以下函数的 C 函数指针:
void doSomething(id self, SEL _cmd);
objc_msgSend
然后 tail-calls 函数指针,
所以方法只是常规的 C 函数,但它们在运行时动态调用。当调用 objc_msgSend
时,return 地址被压入堆栈,CPU 跳转到 objc_msgSend
。它看起来 objc_msgSend
根本没有触及堆栈,因此该方法就像 C 函数一样设置堆栈帧。完成后,该方法完全像 C 函数一样拆除它的堆栈框架和 returns。由于 objc_msgSend
未触及堆栈,因此它 return 直接转到调用方法的代码,就像直接调用方法实现一样。