最近、私は Objective-C ランタイムをいじり回して、いくつかのことがどのように機能するかを調べようとしています。私の「実験」の 1 つで、次のことを行いました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
およびhttp://opensource.apple.com/source/objc4/objc4-532/runtime/objc-abi.h_objc_empty_vtable
で宣言されている両方のランタイム ライブラリ構造体です。ただし、とは で宣言されたクラスを表す構造体であるため、Objective-C ランタイム ライブラリにはこれらのシンボルへの参照はありません。で定義する必要がありますが、そうではないようです。それで、なぜこれが起こるのですか?OBJC_METACLASS_$_MySuperClass
OBJC_CLASS_$_MySuperClass
test.m
teste.o
もう 1 つ: どちらにも、または への壊れた参照はありませOBJC_METACLASS_$_MyClass
んOBJC_CLASS_$_MyClass
。したがって、 と への壊れた参照がObject
ありMySuperClass
、両方とも にサブクラスtest.m
がありますが、サブクラスを持たない への壊れた参照はありMyClass
ません。では、なぜリンカは、実行時ライブラリに、サブクラスを持つクラスへの参照があることを期待しているように見えるのですか?