2012-08-09 89 views
1

這些日子裏,我一直在討論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_$_MySuperClassOBJC_CLASS_$_MySuperClass是表示已在test.m中聲明的類的結構,因此Objective-C運行時庫中沒有這些符號的引用。他們應該在teste.o中定義,但看起來他們不是。那麼,爲什麼會發生?

還有一件事:沒有打破引用OBJC_METACLASS_$_MyClass也沒有OBJC_CLASS_$_MyClass。因此,有ObjectMySuperClass的斷開引用,它們都有test.m中的子類,但沒有對MyClass的斷開引用,它沒有子類。那麼,爲什麼鏈接器似乎期望在運行時庫中引用具有子類的類,而不是那些不具有子類的類?

回答

1

我發現了OBJC_METACLASS_$_<my class name>符號是目標文件中只定義了,如果有一個@implementation <my class name>聲明。所以,如果我加入,例如片段:

@implementation MySuperClass 
-(int) myMessage1 { 
    return 0; 
} 
@end 

test.m,鏈接器將生成錯誤消息:

$ clang -fobjc-nonfragile-abi -fnext-runtime -o class_teste class_teste.m 
/tmp/class_teste-gDWfF6.o:(__DATA, __objc_data+0x0): undefined reference to `OBJC_METACLASS_$_Object' 
/tmp/class_teste-gDWfF6.o:(__DATA, __objc_data+0x8): undefined reference to `OBJC_METACLASS_$_Object' 
/tmp/class_teste-gDWfF6.o:(__DATA, __objc_data+0x10): undefined reference to `_objc_empty_cache' 
/tmp/class_teste-gDWfF6.o:(__DATA, __objc_data+0x18): undefined reference to `_objc_empty_vtable' 
/tmp/class_teste-gDWfF6.o:(__DATA, __objc_data+0x30): undefined reference to `OBJC_CLASS_$_Object' 
/tmp/class_teste-gDWfF6.o:(__DATA, __objc_data+0x38): undefined reference to `_objc_empty_cache' 
/tmp/class_teste-gDWfF6.o:(__DATA, __objc_data+0x40): undefined reference to `_objc_empty_vtable' 
/tmp/class_teste-gDWfF6.o:(__DATA, __objc_data+0x50): undefined reference to `OBJC_METACLASS_$_Object' 
/tmp/class_teste-gDWfF6.o:(__DATA, __objc_data+0x60): undefined reference to `_objc_empty_cache' 
/tmp/class_teste-gDWfF6.o:(__DATA, __objc_data+0x68): undefined reference to `_objc_empty_vtable' 
/tmp/class_teste-gDWfF6.o:(__DATA, __objc_data+0x88): undefined reference to `_objc_empty_cache' 
/tmp/class_teste-gDWfF6.o:(__DATA, __objc_data+0x90): undefined reference to `_objc_empty_vtable' 
/tmp/class_teste-gDWfF6.o:(__DATA, __objc_msgrefs, coalesced+0x0): undefined reference to `objc_msgSend_fixup' 
/tmp/class_teste-gDWfF6.o:(__DATA, __objc_msgrefs, coalesced+0x10): undefined reference to `objc_msgSend_fixup' 
/tmp/class_teste-gDWfF6.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) 

這是相當可以接受的,因爲所有這些不確定的符號的一部分Objective-C運行時庫。由於我的test.m第一個版本是測試用的,因爲我認爲這不會影響到目標文件的符號表我沒有加入到MySuperClass類的實現。所以,這個問題與子類無關。

2

很好的嘗試這些事情。稍後當您遇到類似錯誤並需要調試時將會有所幫助。

那伸出的幾點:

  • 這是不是真正的子類。例如,您可以通過嘗試實例化對象來獲得類似的錯誤。
  • 鏈接器嘗試(簡單地說)將編譯的代碼及其關聯的符號表與代碼中的引用進行匹配。
  • 您沒有MySuperClass的實現,因此沒有生成目標代碼,也沒有符合您的MySuperClass接口定義的符號。通過實現MySuperClass,可以使此錯誤消失。
  • MyClass很好,因爲你已經在文件中實現了MyClass,所以鏈接器可以找到一個有效的符號鏈接到。
+0

是的,你是對的。這就是我剛剛發現的......謝謝! – LuisABOL 2012-08-09 21:39:23

相關問題