Тези дни се забърквах с времето за изпълнение на 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
, но изглежда не са. И така, защо се случва това?
И още нещо: няма нарушена препратка нито към OBJC_METACLASS_$_MyClass
, нито към OBJC_CLASS_$_MyClass
. Следователно има неработещи препратки към Object
и MySuperClass
и двата имат подкласове в test.m
, но няма неработеща препратка към MyClass
, който няма подклас. И така, защо линкерът изглежда очаква да има препратки в библиотеката по време на изпълнение към класовете, които имат подкласове, но не и към тези, които нямат такива?