为什么 ld 链接器允许使用相同方法定义多个类?

Why does the ld linker allow multiple class definitions with the same methods?(为什么 ld 链接器允许使用相同方法定义多个类?)

本文介绍了为什么 ld 链接器允许使用相同方法定义多个类?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

考虑这个文件,first.cpp,包含一个类定义和使用:

Consider this file, first.cpp, containing a class definition and use:

#include <iostream>

struct Foo
{
    Foo(){ std::cout << "Foo()" << std::endl; }
    ~Foo(){ std::cout << "~Foo()" << std::endl; }
};

int main(){
    Foo f;
    return 0;
}

另一个,second.cpp,包含一个冲突的类定义:

and another, second.cpp, containing a conflicting class definition:

#include <iostream>

struct Foo
{
    Foo();
    ~Foo();
};

Foo::~Foo(){ std::cout << "wrong ~Foo()" << std::endl; }

当定义了两个具有相同名称的函数时,链接器会抱怨重复符号,但是这些具有重复类方法的文件编译时不会出错.

The linker complains about duplicate symbols when there are two functions with the same names defined, but these files with duplicate class methods compile without an error.

我用这些命令编译:

$ g++ -c second.cpp -o second
$ g++ second first.cpp -o first

对第二个 g++ 调用的参数重新排序不会改变输出.

Reordering the arguments to the second g++ call doesn't change the output.

first 运行时,输出如下:

And when first is run, this is the output:

$ ./first
Foo()
wrong ~Foo()

为什么链接器允许重复的类方法?如果显然允许,为什么会打印 wrong ~Foo()?

Why does the linker allow duplicate class methods? If it's apparently allowed, why is wrong ~Foo() printed?

推荐答案

再次,未定义的行为.您的程序对 Foo 的析构函数有多个定义,这意味着它违反了 ODR.程序是错误的,任何事情都可能发生.

Again, Undefined Behavior. Your program has multiple definitions for the destructor of Foo, which means that it is in violation of the ODR. The program is wrong and anything can happend.

为什么链接器不接收它?当一个函数在类定义中定义时,它是隐式的inline.编译器通常将这些函数标记为弱符号".然后链接器获取所有翻译单元并尝试解析符号.如果需要,链接器将删除弱符号(即,如果符号已在其他地方定义).

Why does the linker not pick it up? When a function is defined inside the class definition, it is implicitly inline. Compilers usually mark those functions as 'weak symbols'. The linker then gets all translation units and tries to resolve the symbols. Weak symbols will be dropped by the linker if needed (i.e. if the symbol is already defined somewhere else).

从程序的实际输出来看,编译器似乎实际上并没有内联对构造函数的调用,因此在运行时将其分派给链接器留下的符号(非弱符号)

As of the actual output of the program, it looks like the compiler did not actually inline the call to the constructor and thus dispatched at runtime to the symbol that was left by the linker (the non-weak one)

为什么链接器允许有重复的方法?

Why linker allows to have duplicate methods?

因为所有(但最多一个)都是弱符号(即 inline)

Because all (but at most one) are weak symbols (i.e. inline)

为什么在这种情况下会打印错误的~Foo()?

Why, in this case, wrong ~Foo() is printed?

因为调用没有内联,并且链接器丢弃了弱符号

Because the call was not inlined, and the linker dropped the weak symbol

这篇关于为什么 ld 链接器允许使用相同方法定义多个类?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!

本文标题为:为什么 ld 链接器允许使用相同方法定义多个类?

基础教程推荐