【发布时间】:2017-02-08 00:07:26
【问题描述】:
我知道,在 C 语言中,每个函数都会创建一个框架,并且在使用它的函数结束时会自动释放每个框架。相同的逻辑是否适用于 Objective-C 方法?它们在执行时会在堆栈上创建帧吗?
【问题讨论】:
标签: objective-c function methods heap-memory stack-memory
我知道,在 C 语言中,每个函数都会创建一个框架,并且在使用它的函数结束时会自动释放每个框架。相同的逻辑是否适用于 Objective-C 方法?它们在执行时会在堆栈上创建帧吗?
【问题讨论】:
标签: objective-c function methods heap-memory stack-memory
是的,他们有。
Objective-C 动态调用方法,所以:
[someObject doSomething];
相当于:
objc_msgSend(someObject, sel_registerName("doSomething"));
sel_registerName 为给定的方法名称返回一个选择器,它基本上是一个方法标识符。
objc_msgSend 是用汇编编写的,代码可用here。它在对象的方法列表中查找选择器。方法列表包含选择器doSomething 的IMP,它是一个C 函数指针,指向类似以下的函数:
void doSomething(id self, SEL _cmd);
objc_msgSend 然后tail-calls 函数指针,
所以方法只是普通的 C 函数,但它们在运行时被动态调用。当objc_msgSend被调用时,返回地址被压入堆栈,CPU跳转到objc_msgSend。 objc_msgSend 看起来根本没有触及堆栈,因此该方法像 C 函数一样设置堆栈帧。完成后,该方法会拆除它的堆栈帧并完全像 C 函数那样返回。由于objc_msgSend 没有触及堆栈,所以它直接返回到调用该方法的代码,就像直接调用方法实现一样。
【讨论】:
objc_msgSend 的尾调用,这将有效地使帧从堆栈中“消失”,但我不记得这在现代是否可能架构。
objc_msgSend 的尾调用。