调用方法时会发生什么?推论的论点在哪里?

时间:2011-08-03 07:27:17

标签: objective-c ios methods callstack

当您调用方法时,例如[objectA message:arg1 argument:arg2],参数会发生什么变化?

例如,当您调用方法时,该方法的地址将被推送到调用堆栈。但争论会发生什么?他们不是也被推到了一些堆栈吗?否则,该方法的代码如何知道在哪里找到它的参数?

我问的原因是,当您获得堆栈跟踪时,您将获得已按顺序调用的函数或方法的地址。当一个方法或函数返回时,调用它的那个仍然引用它自己的参数。因此,我必须在某处提及arg1arg2。因此,从iOS设备上的堆栈跟踪和堆栈符号,您必须能够获取调用任何其他方法或函数的方法或函数,并获取其参数。

你如何得到这些论点?

关于另一个问题:objective C log method call,他们展示了获取方法NSMethodSignature的方法,并使用它来获取参数的数量和类型。

有了这个,知道参数所在的位置,就可以获得所调用的每个函数或方法以及用于调用它们的参数。

任何帮助将不胜感激。


更新

2011-08-03

在回复“fakeAccount22”评论时,我想在应用程序内的运行时执行此操作。

我的问题基本归结为:在运行时和应用程序内,如何在iOS设备中访问Objective-C中的调用堆栈或堆栈指针?它与Mac OSX不同吗?

2 个答案:

答案 0 :(得分:4)

这里的关键时刻是你调用

[objectA message:arg1 argument:arg2]

你没有调用方法,但你发送消息。为什么?最后这条线由编译器翻译成:

objc_msgSend(objectA, "message:argument:", arg1, arg2)

这就是魔术。其他一切都像在C中一样。这里非常好explanation

这就是为什么所有Objective C方法都可以转换为它们的C-analogous(好吧,它们实际上已被翻译)。例如。您的示例如下所示:

return_type method(id self, SEL _cmd, arg1_type arg1, arg2_type arg2) {
//implementation
}

答案 1 :(得分:2)

除了Max写的内容之外,方法的名称和参数是已知的,因为编译器会生成大量的调试信息,这些信息是从源代码生成的,调试器可以使用它来查找方法的名称以及名称和值当你在没有调试器的情况下运行你的代码时,这个调试信息通常不容易获得,尽管它应该以某种方式可访问,如果你知道它的存储格式。但请注意,它可以随着每个新编辑而改变。

在函数调用之前,参数被调用代码推送到调用堆栈上,并且当对函数进行调用时,处理器也会将返回地址推送到那里。在函数内部,存储堆栈指针,现在堆栈也可用于存储局部变量。在函数结束时,原始堆栈指针被恢复(这使得局部变量无效且不可访问)并且处理器弹出返回地址并在调用之后继续代码。调用者代码除了从堆栈中删除参数并继续其余的代码。

FWIW,就是它在C中发生的情况。还有其他类似的方案,其中项目以不同的顺序被压入堆栈,甚至传递到寄存器中,或者函数从堆栈中清除参数。这种方案称为调用约定。 Obj-C使用cdecl调用约定,这或多或少是我描述它的方式。