这些天来,我一直在玩弄 Objective-C 运行时,试图找出一些事情是如何工作的。在我的一个“实验”中,我做了以下事情:我得到了以下代码,它位于一个名为的文件中test.m
:
#import <objc/Object.h>
@interface MySuperClass: Object {
}
-(int) myMessage1;
@end
@interface MyClass: MySuperClass {
int myIvar;
}
-(void) myMessage2;
@end
@implementation MyClass
-(void) myMessage2 {
myIvar++;
}
@end
int main() {
MyClass *myObject;
myObject = [[MyClass alloc] init];
[myObject myMessage2];
return 0;
}
并试图用clang -fobjc-nonfragile-abi -fnext-runtime -o test test.m
. 可以想象,编译器会生成一个链接错误消息,因为我正在编译一个 Objective-C 文件,但我并没有告诉链接器将它链接到一个 Objective-C 运行时库(-lobjc
例如,使用选项) . 但我是故意这样做的,以检查哪些 objc 运行时库符号将被引用,因此会丢失。我收到以下错误消息:
$ clang -fobjc-nonfragile-abi -fnext-runtime -o test test.m
/tmp/test-jEfgSA.o:(__DATA, __objc_data+0x0): undefined reference to `OBJC_METACLASS_$_Object'
/tmp/test-jEfgSA.o:(__DATA, __objc_data+0x8): undefined reference to `OBJC_METACLASS_$_MySuperClass'
/tmp/test-jEfgSA.o:(__DATA, __objc_data+0x10): undefined reference to `_objc_empty_cache'
/tmp/test-jEfgSA.o:(__DATA, __objc_data+0x18): undefined reference to `_objc_empty_vtable'
/tmp/test-jEfgSA.o:(__DATA, __objc_data+0x30): undefined reference to `OBJC_CLASS_$_MySuperClass'
/tmp/test-jEfgSA.o:(__DATA, __objc_data+0x38): undefined reference to `_objc_empty_cache'
/tmp/test-jEfgSA.o:(__DATA, __objc_data+0x40): undefined reference to `_objc_empty_vtable'
/tmp/test-jEfgSA.o:(__DATA, __objc_msgrefs, coalesced+0x0): undefined reference to `objc_msgSend_fixup'
/tmp/test-jEfgSA.o:(__DATA, __objc_msgrefs, coalesced+0x10): undefined reference to `objc_msgSend_fixup'
/tmp/test-jEfgSA.o:(__DATA, __objc_msgrefs, coalesced+0x20): undefined reference to `objc_msgSend_fixup'
clang: error: linker command failed with exit code 1 (use -v to see invocation)
很容易理解为什么列出的一些符号是未定义的。objc_msgSend_fixup
,例如,指的是运行时库函数。_objc_empty_cache
并且_objc_empty_vtable
都是在http://opensource.apple.com/source/objc4/objc4-532/runtime/objc-abi.h中声明的运行时库结构。但是,OBJC_METACLASS_$_MySuperClass
和OBJC_CLASS_$_MySuperClass
是表示已在 中声明的类的结构test.m
,因此在 Objective-C 运行时库中没有对这些符号的引用。它们应该在 中定义teste.o
,但似乎不是。那么,为什么会发生这种情况?
还有一件事:没有对 no 或 的损坏OBJC_METACLASS_$_MyClass
引用OBJC_CLASS_$_MyClass
。因此,存在对 and 的损坏引用,Object
并且MySuperClass
它们在 中都有子类test.m
,但对 没有损坏的引用MyClass
,它没有子类。那么,为什么链接器似乎期望在运行时库中有对具有子类的类的引用,而不是对那些没有子类的引用呢?