【问题标题】:Does the execution of Objective-C methods create "frames on the stack"?Objective-C 方法的执行是否会创建“堆栈上的帧”?
【发布时间】:2017-02-08 00:07:26
【问题描述】:

我知道,在 C 语言中,每个函数都会创建一个框架,并且在使用它的函数结束时会自动释放每个框架。相同的逻辑是否适用于 Objective-C 方法?它们在执行时会在堆栈上创建吗?

【问题讨论】:

    标签: objective-c function methods heap-memory stack-memory


    【解决方案1】:

    是的,他们有。


    Objective-C 动态调用方法,所以:

    [someObject doSomething];
    

    相当于:

    objc_msgSend(someObject, sel_registerName("doSomething"));
    

    sel_registerName 为给定的方法名称返回一个选择器,它基本上是一个方法标识符。

    objc_msgSend 是用汇编编写的,代码可用here。它在对象的方法列表中查找选择器。方法列表包含选择器doSomethingIMP,它是一个C 函数指针,指向类似以下的函数:

    void doSomething(id self, SEL _cmd);
    

    objc_msgSend 然后tail-calls 函数指针,

    所以方法只是普通的 C 函数,但它们在运行时被动态调用。当objc_msgSend被调用时,返回地址被压入堆栈,CPU跳转到objc_msgSendobjc_msgSend 看起来根本没有触及堆栈,因此该方法像 C 函数一样设置堆栈帧。完成后,该方法会拆除它的堆栈帧并完全像 C 函数那样返回。由于objc_msgSend 没有触及堆栈,所以它直接返回到调用该方法的代码,就像直接调用方法实现一样。

    【讨论】:

    • 好,简洁,回答。这里有一个不那么简洁的答案(有更多信息):stackoverflow.com/questions/2189212/…。我认为优化有可能产生对objc_msgSend 的尾调用,这将有效地使帧从堆栈中“消失”,但我不记得这在现代是否可能架构。
    • @bbum 是的,clang 生成对objc_msgSend 的尾调用。
    • @robmayoff 谢谢。这么多架构……这么多编译器……这么多年。 :)
    猜你喜欢
    • 2014-01-06
    • 2017-11-21
    • 2010-12-06
    • 2013-11-04
    • 1970-01-01
    • 1970-01-01
    • 2019-02-19
    • 2015-12-01
    • 2019-04-15
    相关资源
    最近更新 更多