我想知道谁将在objective-c中调用main方法?
我知道UIApplicationMain(nil,nil,nil,NSStringFromClass [Appdelgate class])方法是从main()方法调用,然后从appdelegate didFinishLaunchingWithOptions()方法继续处理.....
我也知道java中的main()方法是由JVM调用的,而进程是从main()方法继续进行的。
就像那样,我想知道谁会在objective-c中调用main()。
感谢您的帮助
答案 0 :(得分:3)
找出答案的简单方法是在main()
中加一个断点并查看:
从技术上讲,问题的答案是从名为main()
的东西调用start
。您没有获得start
的源代码,但是如果需要,您可以查看调试器中的汇编代码。此版本来自为模拟器构建的代码:
0x1c30: pushl $0
0x1c32: movl %esp, %ebp
0x1c34: andl $-16, %esp
0x1c37: subl $16, %esp
0x1c3a: movl 4(%ebp), %ebx
0x1c3d: movl %ebx, (%esp)
0x1c40: leal 8(%ebp), %ecx
0x1c43: movl %ecx, 4(%esp)
0x1c47: addl $1, %ebx
0x1c4a: shll $2, %ebx
0x1c4d: addl %ecx, %ebx
0x1c4f: movl %ebx, 8(%esp)
0x1c53: movl (%ebx), %eax
0x1c55: addl $4, %ebx
0x1c58: testl %eax, %eax
0x1c5a: jne 0x00001c53 ; start + 35
0x1c5c: movl %ebx, 12(%esp)
0x1c60: calll 0x00001c70 ; main at main.m:9
0x1c65: movl %eax, (%esp)
0x1c68: calll 0x00002376 ; exit
0x1c6d: hlt
0x1c6e: nop
0x1c6f: nop
如果您创建一个MacOS X命令行程序并在main()
中放置一个断点,您会发现桌面上的main()
也会调用start
。 Mac版start
的程序集并不完全相同,但它非常接近。因此,很好的猜测是编译器基于目标平台为您生成start
,并且start
是操作系统在启动程序时查找的入口点。
答案 1 :(得分:2)
我相信它是由Obj-C运行时库中的汇编例程调用的,与C中的相同,但是带有C运行时库
答案 2 :(得分:2)
在大多数系统中,操作系统具有负责将可执行程序加载到内存中的特殊功能。它们分配所需的内存并将文件中的信息加载到该空间中。在某些情况下,它们甚至可以对代码进行特殊修改,以便它可以在加载它的特定内存空间中工作。
将程序加载到内存后,操作系统将控制权传递给程序文件代码段的开头。代码段的开头通常有一个小例程,它执行一些必要的操作,如初始化堆栈和内存堆。当这些事情完成后,它会将控制传递给main()函数。
答案 3 :(得分:1)
由于Objective-C是C的衍生物,因此很多内部结构都是相似的(这就是为什么你可以将C \ C ++代码与Objective-C混合))。因此,当两者都编译成可执行文件时,它们会在类似的系统中运行。这也是为什么Objective-C是由gcc或Clang编译的。
考虑到这一点,编译时会发生什么?所有的C代码都转换为Assembly \ machine代码(因为Assembly只是机器代码的助记符版本)。程序集的级别低于Java; CPU只是运行它并按顺序执行每个单独的指令。 C语言中的main()
函数是编译器“知道”指令开始位置的地方。完成所有声明后,main()
函数会被一个名为“jmp
”的指令跳转到。
那么当您在Xcode中编译并启动时会发生什么?首先,gcc / Clang将代码转换为Assembly \ machine代码。其次,Xcode将二进制文件加载到内存中。第三,Darwin(OS X或iOS,或任何操作系统)认识到这是一个可执行的内存区域,从指令集的顶部开始并贯穿每条指令。
要回答您的问题,main()
功能由CPU启动。这与Java不同,后者具有独立于平台的指令集,该指令集在JVM中“模拟”。
This问题有一个很好的答案,可以解释main()
函数如何转换为汇编代码。