Objective-C源代码编译中对符号的未定义引用

Objective-C源代码编译中对符号的未定义引用,objective-c,objective-c-runtime,Objective C,Objective C Runtime,这些天来,我一直在摆弄Objective-C运行时,试图找出一些东西是如何工作的。在我的一个“实验”中,我做了以下工作:我得到了一个名为test.m的文件中的以下代码: #import <objc/Object.h> @interface MySuperClass: Object { } -(int) myMessage1; @end @interface MyClass: MySuperClass { int myIvar; } -(void) myMessage2;

这些天来,我一直在摆弄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;
}
很容易理解为什么列出的一些符号没有定义<例如,code>objc\u msgSend\u fixup是指运行时库函数
\u objc\u empty\u cache
\u objc\u empty\u vtable
都是中声明的运行库结构。但是,
OBJC\u元类$\u MySuperClass
OBJC\u类$\u MySuperClass
是表示已在
test.m
中声明的类的结构,因此Objective-C运行库中没有对这些符号的引用。它们应该在teste.o中定义,但似乎不是。那么,为什么会发生这种情况


还有一件事:对
OBJC\u元类$\u MyClass
OBJC\u类$\u MyClass
都没有断开的引用。因此,有对
对象
MySuperClass
的断开引用,它们都在
test.m
中有子类,但没有对没有子类的
MyClass
的断开引用。那么,为什么链接器似乎希望在运行库中有对有子类的类的引用,而不是对没有子类的类的引用呢?

很好地尝试了这类东西。当您以后遇到类似错误并需要调试时,它将非常有用

突出的几点:

  • 这并不是真正的子类化。例如,仅通过尝试实例化一个对象,就可能会出现类似的错误
  • 链接器尝试(用简化的术语)匹配编译后的代码及其关联的符号表,以及代码中的引用
  • 您没有MySuperClass的实现,因此不会生成任何对象代码,也不存在与您的MySuperClass接口定义匹配的符号。通过实现MySuperClass,可以消除此错误
  • MyClass很好,因为您已经在文件中实现了MyClass,所以链接器可以找到要链接到的有效符号

我发现只有在存在
@implementation
语句时,才会在对象文件中定义
OBJC\u元类$
符号。例如,如果我添加以下代码段:

@implementation MySuperClass
-(int) myMessage1 {
  return 0;
}
@end
test.m
,链接器将生成错误消息:

$ 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)
$ 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
类添加实现,因为我认为它不会影响对象文件的符号表。因此,问题与子类化无关。

是的,你完全正确。这就是我刚刚发现的。。。谢谢