Multiple definitions of inline function C++

Viewed 161

I know there is already a lot of topics about this subject, however I didn't find in any of them the explanation to how it is possible to have one definition of an inline function per translation unit. I know that inline functions have external linkage, so when I call one inline function in different translation units they all reference the same function. I also know that in Linux the compiler registers inline function with the "W" symbol, so it is registered as a weak symbol (thanks to it the first definition encountered by the compiler of the inline function is the one considered). However whenever I use nm on the object files created by g++ in Windows there is no weak symbol attached to the function signature. How can the linker know which definition to consider and not to accuse of multiple definitions? (I don't show the linker's work but I tested it).

Here is some example code:

// main1.cpp
#include "main.hpp"

/* inline accepts one definition in each TU's */

inline void Test::hello_world()
{
    std::cout << "Hello world" << std::endl;
}

/*void Test::hello_world()
{
    std::cout << "Hello world" << std::endl;
}*/

extern void return_hello_world();

int main()
{
    Test t;
    t.hello_world();
    return_hello_world();
    return 0;
}

// main2.cpp
#include "main.hpp"

/* inline accepts one definition in each TU's */

inline void Test::hello_world()
{
    std::cout << "Hello world" << std::endl;
}

/* void Test::hello_world()
{
    std::cout << "Hello world" << std::endl;
} */

void return_hello_world()
{
    Test t;
    t.hello_world();
}

// main.hpp
#ifndef TEST
#define TEST
#include <iostream>

class Test
{
public:
    void hello_world();
};

#endif

The results I receive are:

  • Windows:
    Experimentation4> g++ -g -O0 -c main1.cpp main2.cpp
    Experimentation4> nm main1.o
    0000000000000000 b .bss  
    0000000000000000 d .ctors
    0000000000000000 d .data 
    0000000000000000 N .debug_abbrev 
    0000000000000000 N .debug_aranges
    0000000000000000 N .debug_frame  
    0000000000000000 N .debug_info   
    0000000000000000 N .debug_line  
    0000000000000000 N .debug_ranges
    0000000000000000 N .debug_str   
    0000000000000000 p .pdata       
    0000000000000000 p .pdata$_ZN4Test11hello_worldEv
    0000000000000000 r .rdata
    0000000000000000 r .rdata$.refptr._ZSt4cout      
    0000000000000000 r .rdata$.refptr._ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_
    0000000000000000 r .rdata$zzz
    0000000000000000 R .refptr._ZSt4cout
    0000000000000000 R .refptr._ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_
    0000000000000000 t .text
    0000000000000000 t .text$_ZN4Test11hello_worldEv
    0000000000000000 r .xdata
    0000000000000000 r .xdata$_ZN4Test11hello_worldEv
                     U __main
    0000000000000029 t __tcf_0
    0000000000000080 t _GLOBAL__sub_I_main
                     U _Z18return_hello_worldv
    0000000000000044 t _Z41__static_initialization_and_destruction_0ii
    0000000000000000 T _ZN4Test11hello_worldEv
                     U _ZNSolsEPFRSoS_E
                     U _ZNSt8ios_base4InitC1Ev
                     U _ZNSt8ios_base4InitD1Ev
                     U _ZSt4cout
                     U _ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_
    0000000000000000 r _ZStL19piecewise_construct
    0000000000000000 b _ZStL8__ioinit
                     U _ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc
                     U atexit
    0000000000000000 T main
  • Linux:
    Experimentation2$ g++ -O0 -g -c main1.cpp main2.cpp
    Experimentation2$ nm main1.o
                     U __cxa_atexit
                     U __dso_handle
    0000000000000081 t _GLOBAL__sub_I_main
    0000000000000000 T main
                     U __stack_chk_fail
                     U _Z18return_hello_worldv
    0000000000000043 t _Z41__static_initialization_and_destruction_0ii
    0000000000000000 W _ZN4Test11hello_worldEv
                     U _ZNSolsEPFRSoS_E
                     U _ZNSt8ios_base4InitC1Ev
                     U _ZNSt8ios_base4InitD1Ev
                     U _ZSt4cout
                     U _ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_
    0000000000000000 b _ZStL8__ioinit
                     U _ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc
0 Answers
Related