简体   繁体   English

linker 是否将 object 文件与其自身链接?

[英]Does linker link an object file with itself?

From what I read in other SO answers, like this and this , compiler converts the source code into object file.根据我在其他 SO 答案中读到的内容,例如thisthis ,编译器将源代码转换为 object 文件。 And the object files might contain references to functions like printf that needs to be resolved by the linker. object 文件可能包含对printf等需要由 linker 解决的函数的引用。

What I don't understand is, when both declaration and definition exist in the same file, like the following case, does compiler or linker resolve the reference to return1 ?我不明白的是,当声明和定义都存在于同一个文件中时,如以下情况,编译器或 linker 是否解析对return1的引用

Or is this just a part of the compiler optimization?或者这只是编译器优化的一部分?

int return1();

int return2() {
  int b = return1();
  return b + 1;
}

int return1() {
  return 1;
}

int main() {
  int b = return2();
}

I have ensured that preprocessing has nothing to do with this by running g++ -E main.cpp .我通过运行g++ -E main.cpp确保预处理与此无关


Update 2020-7-22 2020-7-22 更新

The answers are all helpful!答案都很有帮助! Thanks!谢谢!

From the answers below, it seems to me that the compiler may or may not resolve the reference to return1 .从下面的答案来看,在我看来,编译器可能会也可能不会解析对return1的引用。 However, I'm still unclear if there's only one translation unit , like the example I gave, and if compiler did not resolve it, does this mean that linker must resolve it then?但是,我仍然不清楚是否只有一个翻译单元,就像我给出的示例一样,如果编译器没有解决它,这是否意味着 linker必须解决它?

Since it seems to me that linker will link several (greater than one) object files together, and if there's only one translation unit (object file) , linker need to link the object file with itself, am I right? Since it seems to me that linker will link several (greater than one) object files together, and if there's only one translation unit (object file) , linker need to link the object file with itself, am I right?

And is there anyway to know for sure which one is the case on my computer?无论如何,是否可以确定我的计算机上的情况是哪一个?

It depends.这取决于。 Both options are possible, so are options that you didn't mention, like either the compiler or the linker rearranging the code so that none of the functions exist any more.这两个选项都是可能的,您没有提到的选项也是可能的,例如编译器或 linker 重新排列代码以便不再存在任何函数。 It's fine thinking about compilers emitting references to functions and linkers resolving those references as a way of understanding C++, but bear in mind is that all the compiler and linker have to do is produce a working program and there are many different ways to do that.最好考虑编译器发出对函数的引用,而链接器将这些引用解析为理解 C++ 的一种方式,但请记住,所有编译器和 linker 所要做的就是生成一个工作程序,并且有许多不同的方法可以做到这一点。

One thing the compiler and linker must do however, is make sure that any calls to standard library functions happen (like printf as you mentioned), and happen in the order that the C++ source specifies.然而,编译器和 linker 必须做的一件事是确保对标准库函数的任何调用都发生(如您提到的printf ),并按照 ZF6F87C9FDCF8B3C3F07F93F1EE8712CZ 源指定的顺序发生。 Apart from that (and some other similar concerns) they can more or less do as they wish.除此之外(以及其他一些类似的问题),他们或多或少可以随心所欲。

[lex.phases]/1.9 , covering the final phase of translation , states [ emphasis mine]: [lex.phases]/1.9 ,涵盖翻译的最后阶段,指出[强调我的]:

All external entity references are resolved.所有外部实体引用均已解析。 Library components are linked to satisfy external references to entities not defined in the current translation .链接库组件以满足对当前翻译中未定义的实体的外部引用。 All such translator output is collected into a program image which contains information needed for execution in its execution environment.所有此类翻译器 output 都被收集到一个程序映像中,该程序映像包含在其执行环境中执行所需的信息。

It is, however, up to the compiler to decide whether a library component is a single translation unit or a combination of them;但是,由编译器决定库组件是单个翻译单元还是它们的组合; as governed by [lex.separate]/2 [ emphasis mine]:根据[lex.separate]/2 [强调我的]:

[ Note: Previously translated translation units and instantiation units can be preserved individually or in libraries . [注意:以前翻译的翻译单元和实例化单元可以单独保存或保存在库中 The separate translation units of a program communicate ([basic.link]) by (for example) calls to functions whose identifiers have external linkage, manipulation of objects whose identifiers have external linkage, or manipulation of data files.程序的单独翻译单元通过(例如)调用标识符具有外部链接的函数、标识符具有外部链接的对象的操作或数据文件的操作来通信([basic.link])。 Translation units can be separately translated and then later linked to produce an executable program.翻译单元可以单独翻译,然后链接以生成可执行程序。 — end note ] ——尾注]


OP: [...] does compiler or linker resolve the reference to return1 ? OP:[...] 编译器或 linker 是否解析对return1的引用?

Thus, even if return1 has external linkage, as it is defined in the translation unit where it is referred to (in return2 ), the linker should not need to resolve the reference to it, as its is definition exists in the current translation.因此,即使return1具有外部链接,正如它在引用它的翻译单元中定义的那样(在return2中),linker 也不应该需要解析对它的引用,因为它的定义存在于当前翻译中。 The standard passage is, however, (likely intentionally) a bit vague regarding requirements for when linking to satisfy external references need to occur, and I do not see it to be a non-compliant implementation to defer resolving the reference to return1 in return2 until the linking phase.然而,标准段落(可能是故意)对于何时需要进行链接以满足外部引用的要求有点模糊,我认为推迟解析return1 return2引用直到链接阶段。

Practically speaking, the problem is with the following code:实际上,问题在于以下代码:

static int return1();

int return2() {
  int b = return1();
  return b + 1;
}

int return1() {
  return 1;
}

The problem for the linker is that each Translation Unit can now contain its own return1 , so the linker would have a problem in choosing the right return1 . linker 的问题是每个翻译单元现在都可以包含自己的return1 ,因此 linker 在选择正确的return1时会有问题。 There are tricks around this, eg adding the Translation Unit name to the function name.有一些技巧可以解决这个问题,例如将翻译单元名称添加到 function 名称中。 Most ABI's do not do that, but the C++ standard would allow it.大多数 ABI 不这样做,但 C++ 标准允许这样做。 For anonymous namespaces however, ie namespace { int function1(); }然而,对于匿名命名空间,即namespace { int function1(); } namespace { int function1(); } , ABI's will use such tricks. namespace { int function1(); } ,ABI 将使用这样的技巧。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM