How does the linker handle identical template instances between translation units?

Suppose I have two translation units:

foo.cpp

void foo() {
  auto v = std::vector<int>();
}

bar.cpp

void bar() {
  auto v = std::vector<int>();
}

When I compile these translation units, each copy will be std::vector<int>.

My question is: how does this work in the binding phase?

  • Do both instances have different distorted names?
  • Does the linker delete them as duplicates?
+4
source share
3 answers

++ , , . , . , , , . - .

++ ++, , ++: , . , , . , GCC ++ GNU linker .

, , ++- - - , - , - . .

, , , , , .

, , : , ODR , - , "" . , , .

:

thing.hpp

#ifndef THING_HPP
#define THING_HPP
#ifndef ID
#error ID undefined
#endif

template<typename T>
struct thing
{
    T id() const {
        return T{ID};
    }
};

#endif

ID - , .

:

foo.cpp

#define ID 0xf00
#include "thing.hpp"

unsigned foo()
{
    thing<unsigned> t;
    return t.id();
}

foo, thing<unsigned> t, t.id(). , thing<unsigned>, foo, : -

  • , .

:

boo.cpp

#define ID 0xb00
#include "thing.hpp"

unsigned boo()
{
    thing<unsigned> t;
    return t.id();
}

foo.cpp, , boo foo ID= 0xb00.

, , :

main.cpp

#include <iostream>

extern unsigned foo();
extern unsigned boo();

int main()
{
    std::cout << std::hex 
    << '\n' << foo()
    << '\n' << boo()
    << std::endl;
    return 0;
}

, hex, foo() - = f00 - boo() - = b00.

foo.cpp, -save-temps, :

g++ -c -save-temps foo.cpp

foo.s, thing<unsigned int>::id() const (mangled = _ZNK5thingIjE2idEv):

    .section    .text._ZNK5thingIjE2idEv,"axG",@progbits,_ZNK5thingIjE2idEv,comdat
    .align 2
    .weak   _ZNK5thingIjE2idEv
    .type   _ZNK5thingIjE2idEv, @function
_ZNK5thingIjE2idEv:
.LFB2:
    .cfi_startproc
    pushq   %rbp
    .cfi_def_cfa_offset 16
    .cfi_offset 6, -16
    movq    %rsp, %rbp
    .cfi_def_cfa_register 6
    movq    %rdi, -8(%rbp)
    movl    $3840, %eax
    popq    %rbp
    .cfi_def_cfa 7, 8
    ret
    .cfi_endproc

:

.section    .text._ZNK5thingIjE2idEv,"axG",@progbits,_ZNK5thingIjE2idEv,comdat

.text._ZNK5thingIjE2idEv, , , .text ( ) , . , , .text.<function_name>, . , <function_name>.

:

.weak   _ZNK5thingIjE2idEv

. thing<unsigned int>::id() const weak. GNU . . , . , . ( ) , . , .

:

.type   _ZNK5thingIjE2idEv, @function

thing<unsigned int>::id() - .

_ZNK5thingIjE2idEv, .LFB2. 3840 (= 0xf00).

boo.cpp :

g++ -c -save-temps boo.cpp

, thing<unsigned int>::id() boo.s

    .section    .text._ZNK5thingIjE2idEv,"axG",@progbits,_ZNK5thingIjE2idEv,comdat
    .align 2
    .weak   _ZNK5thingIjE2idEv
    .type   _ZNK5thingIjE2idEv, @function
_ZNK5thingIjE2idEv:
.LFB2:
    .cfi_startproc
    pushq   %rbp
    .cfi_def_cfa_offset 16
    .cfi_offset 6, -16
    movq    %rsp, %rbp
    .cfi_def_cfa_register 6
    movq    %rdi, -8(%rbp)
    movl    $2816, %eax
    popq    %rbp
    .cfi_def_cfa 7, 8
    ret
    .cfi_endproc

, : 2816 (= 0xb00).

, , , : ( ), . , : -

  • .

, thing<T> T = unsigned. , thing<unsigned> , _ZNK5thingIjE2idEv a.k.a thing<unsigned int>::id() const.

, , thing<unsigned> . thing<unsigned> -, , -, .

, .

.

g++ -c main.cpp

, _ZNK5thingIjE2idEv, :

g++ -o prog main.o foo.o boo.o -Wl,--trace-symbol='_ZNK5thingIjE2idEv',-M=prog.map
foo.o: definition of _ZNK5thingIjE2idEv
boo.o: reference to _ZNK5thingIjE2idEv

, , _ZNK5thingIjE2idEv foo.o boo.o.

, :

./prog

f00
f00

foo() boo() thing<unsigned>().id() foo.cpp.

thing<unsigned int>::id() const boo.o? :

prog.map

...
Discarded input sections
 ...
 ...
 .text._ZNK5thingIjE2idEv
                0x0000000000000000        0xf boo.o
 ...
 ...

boo.o, .

prog , foo.o boo.o :

$ g++ -o prog main.o boo.o foo.o -Wl,--trace-symbol='_ZNK5thingIjE2idEv',-M=prog.map
boo.o: definition of _ZNK5thingIjE2idEv
foo.o: reference to _ZNK5thingIjE2idEv

_ZNK5thingIjE2idEv boo.o foo.o. , :

$ ./prog

b00
b00

:

...
Discarded input sections
 ...
 ...
 .text._ZNK5thingIjE2idEv
                0x0000000000000000        0xf foo.o
 ...
 ...

.text._ZNK5thingIjE2idEv foo.o.

.

. , , . , - , - , - . , . , , .

, , , , , . , ODR , , . #include - ( ) - .

+4

.

GNU, , . , .

Sun Solaris, , . , , . , . , .

.

+1

, , class Bar {...};, , . , ? , ? , . , , ODR, , , , , - , - . , , , , (. ODR ), , , Bar, std::vector<int>. - , - .

0

Source: https://habr.com/ru/post/1678437/


All Articles