2

C++ translator seems uses correct declared structs of the same name, but then linker mismatches them without any warning or error! And this also leads to UB, because at least inappropriate ctor/dtor are used for the memory region.

Here is minimal sandbox code. Each struct Test should be treated as some internal non-public structure used only in one own .cpp file.

file1.cpp

#include <iostream>

using namespace std;
void someFunc();


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


int main()
{
    {
        Test test;
    }

    someFunc();

    return 0;
}

file2.cpp

#include <iostream>

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

void someFunc() {
    Test test;
}

(Downloadable and buildable CMake-project just in case: https://file.io/dzafv409B2t0)

Output will be:

1  ~1
1  ~1

So, I expected:

  • Successful build with output: 1 ~1 2 ~2
  • Or failed build with multiple definition error

Yes, I can resolve the problem if:

  • Rename the struct
  • Put the struct into anonymous namespace - force internal linkage

...but this doesn't answer the main question:

  • Why linker behaves so? Why does it silently links to first available matching symbol (among several) instead of reporting multiple definition error?

Update: As I understood, this mechanism allows to include header with class declaration (with inline code) into several different source files without multiple definition problem.

Ihor Drachuk
  • 1,265
  • 7
  • 17
  • 1
    if this caused a multiple definition error you wouldn't be able to define structures in header files – Alan Birtles Apr 27 '21 at 14:23
  • @AlanBirtles, Ok, now I see. Thank you – Ihor Drachuk Apr 27 '21 at 14:27
  • yes but the behaviour would be the same if `Test` was defined in a header, headers are just effectively copy and pasted into your cpp file – Alan Birtles Apr 27 '21 at 14:27
  • 1
    The local `struct Test` in each file should be surrounded in a `namespace {` ... `}`. The anonymous namespace will make each of those things local to the translation unit. – Eljay Apr 27 '21 at 14:34

0 Answers0