【问题标题】:Undefined references to symbols on Objective-C source compilation在 Objective-C 源代码编译中未定义的符号引用
【发布时间】:2012-08-09 19:15:49
【问题描述】:

这些天来,我一直在玩弄 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_$_MySuperClassOBJC_CLASS_$_MySuperClass 是表示已在 test.m 中声明的类的结构,因此在 Objective-C 运行时库中没有对这些符号的引用。它们应该在teste.o 中定义,但似乎不是。那么,为什么会这样呢?

还有一件事:没有对OBJC_METACLASS_$_MyClassOBJC_CLASS_$_MyClass 的引用。因此,有对ObjectMySuperClass 的损坏引用,它们在test.m 中都有子类,但没有对MyClass 的损坏引用,它没有子类。那么,为什么链接器似乎期望在运行时库中存在对具有子类的类的引用,而不是对那些没有子类的类的引用?

【问题讨论】:

    标签: objective-c objective-c-runtime


    【解决方案1】:

    很高兴尝试这些事情。以后遇到类似错误需要调试时会有所帮助。

    突出的几点:

    • 这实际上与子类化无关。例如,仅通过尝试实例化一个对象,您可能会遇到类似的错误。
    • 链接器尝试(以简化的方式)将编译后的代码及其关联的符号表与代码中的引用进行匹配。
    • 您没有 MySuperClass 的实现,因此不会生成目标代码,也不存在与您的 MySuperClass 接口定义匹配的符号。您可以通过实现 MySuperClass 来消除此错误。
    • MyClass 没问题,因为你已经在文件中实现了 MyClass,所以链接器可以找到一个有效的符号来链接。

    【讨论】:

    • 是的,你完全正确。这就是我刚刚发现的...谢谢!
    【解决方案2】:

    我发现只有在有@implementation &lt;my class name&gt; 语句的情况下,才会在目标文件中定义OBJC_METACLASS_$_&lt;my class name&gt; 符号。因此,如果我添加例如 sn-p:

    @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 类添加实现,因为我认为它不会影响目标文件的符号表。所以,这个问题与子类化无关。

    【讨论】:

      猜你喜欢
      • 2011-02-19
      • 1970-01-01
      • 2013-03-07
      • 2011-11-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多