如果.m在头文件

时间:2017-09-12 08:32:37

标签: ios objective-c xcode

为什么导入.m文件会导致链接器错误?

PS :如果您发现此问题太小[或摘要]无法解答,请在评论中发帖。我会尝试发布几个场景。但是,这是iOS开发人员很容易熟悉的一般行为。

1 个答案:

答案 0 :(得分:0)

以下是构建过程的简要概述。编译器的输入称为"翻译单元"。翻译单元是.m文件,其中包含所有包含/导入的头文件的内容。它将每个翻译单元分别编译为目标文件(.o)。每个目标文件都有一个符号表,其中包含在关联的转换单元中定义的所有符号。在此阶段,符号只是可以从生成的代码中引用的名称。然后,链接器的工作是将地址与每个符号相关联,然后通过其地址替换生成的代码中的符号的每个引用,以生成最终的可执行文件。在目标文件的符号表中,您可以使用已定义或未定义的符号。未定义的符号是在目标文件中引用但未在其中定义的符号。链接器需要在此过程的后期在另一个目标文件中找到合适的定义。定义的符号表示目标文件提供符号的定义。当链接器在目标文件的符号表中遇到这样的符号时,它可以立即将其分配给地址。如果稍后它找到另一个具有相同名称的已定义(全局)符号的目标文件,它将以重复的符号错误停止。

我们以下列.m个文件为例:

A.M:

int my_global;

b.m:

#include "a.m"

my_global = 3;

编译器会看到以下两个翻译单元:

一个:

int my_global;

B:

int my global;
my_global = 3;

它单独处理它们,并发出a.o和b.o,它们的符号表中都有符号my_global作为定义的符号。当链接器遇到两者中的第二个时,它会抱怨重复的符号。

要解决此问题,您可以创建一个名为a.h的头文件,其中包含my_global的外部声明,并包含b.m中的声明:

A.H

extern int my_global;

b.m

#include "a.h"

my_global = 3;

b翻译单位现在是:

extern int my_global;

my_global = 3;

现在符号将在b.o中未定义,链接器会将其解析为a.o中定义的符号。

有关链接器的更多信息,请阅读this excellent article