這些日子裏,我一直在討論Objective-C運行時,試圖找出有些東西是如何工作的。在我的「實驗」一,我做了以下內容:我得到了下面的代碼是在一個名爲test.m
文件:未定義的Objective-C源代碼編譯符號引用
#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
中定義,但看起來他們不是。那麼,爲什麼會發生?
還有一件事:沒有打破引用OBJC_METACLASS_$_MyClass
也沒有OBJC_CLASS_$_MyClass
。因此,有Object
和MySuperClass
的斷開引用,它們都有test.m
中的子類,但沒有對MyClass
的斷開引用,它沒有子類。那麼,爲什麼鏈接器似乎期望在運行時庫中引用具有子類的類,而不是那些不具有子類的類?
是的,你是對的。這就是我剛剛發現的......謝謝! – LuisABOL 2012-08-09 21:39:23