Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Template static member definition depends on order passed to linker

The following code, which has 2 definitions for a template static field member, each definition defines template1<int>::x with a different value.

One would expect the linker to reject such redefinitions as they have different values.

But compilation & linkage passes for both g++ and MSVC, and which definition is used is dependent on the order in which the sources are passed to the linker.

Is this behavior compliant to the C++ standard, undefined behavior, or a linker bug?

my_template.h

template <class T>
class template1
{
public:
    static int x;
};

Src2.cpp

#include <stdio.h>
#include "my_template.h"

template <class T>
int template1<T>::x = 2; 

void my_func() // definition
{
    printf("my_func: template1<int>::x = %d\n", template1<int>::x); // definition of X to 2.
    printf("my_func: template1<char>::x = %d\n", template1<char>::x); // definition of X to 2.
}

Main.cpp

#include <cstdio>
#include "my_template.h"

template <class T>
int template1<T>::x = 1;

void my_func();

int main()
{
    printf("main: template1<int>::x = %d\n", template1<int>::x); // definition of X to 1.
    my_func();
    return 0;
}

Compile with g++ (MinGW.org GCC Build-20200227-1) 9.2.0+

Compile1

g++ -o prog Src2.cpp Main.cpp

Output1

main: template1<int>::x = 2
my_func: template1<int>::x = 2
my_func: template1<char>::x = 2

Compile2

g++ -o prog Main.cpp Src2.cpp

Ouput2

main: template1<int>::x = 1
my_func: template1<int>::x = 1
my_func: template1<char>::x = 2

Observed also with

Microsoft (R) C/C++ Optimizing Compiler Version 19.25.28612 for x86

When I disassembled the code with -S flag, each compilation unit defined the same symbol name.

Co-work with Nightra.

like image 381
Tony Tannous Avatar asked Mar 02 '23 13:03

Tony Tannous


1 Answers

This violates ODR (which requires that an entity must have exactly one definition, if it's used). So the program has UB.

The compiler couldn't diagnose this, because each translation unit is fine. In theory, the linker could diagnose this, but in practice it won't do that.

like image 178
cigien Avatar answered Mar 05 '23 15:03

cigien