Search code examples
c++templatessymbolsspecializationweak

My template specialization differs debug version from release version, is this gcc bug?


First of all, I've got a header file for a class, an specialization declaration without definition(code samples from internet)

$ cat foo.h

template<typename T>
class foo{
public:
  static void init(){
      return;
  }

};

template<>  void foo<int>::init();

Then there're 2 implementation files for template specialization

$ cat foo_int.cpp 
#include "foo.h"
#include<stdio.h>
template<>
void foo<int>::init(){
    printf("init int foo\n");
}

$ cat foo_float.cpp 
#include "foo.h"
#include<stdio.h>
template<>
void foo<float>::init(){
    printf("init float foo\n");
}

Finally I got a main file

$ cat main.cpp
#include "foo.h"

int main(){
  foo<int>::init();
  foo<float>::init();
}

If I compile it without optimization and run it, it gives:

g++ foo_int.cpp foo_float.cpp main.cpp && a.out
init int foo
init float foo

If I add optimization, then the result is different:

$ g++ foo_int.cpp foo_float.cpp main.cpp -O2 && a.out
init int foo

The result is different. Some explanation from internet said this is due to some internal mechanism of "weak symbol" in gcc implementation, but my question:

  1. Is "weak symbol"/"strong symbol" a concept of gcc/g++, or it's part of the c/c++ language specification.

  2. If debug and release results are different, should I say this is a bug/issue of gcc/g++, in regard with "weak symbol" mechanism? As a developer, I wouldn't expect my debug version to behave differently from release version.

I tried clang, unfortunately same error. Is this an "acceptable" case for C/C++ that debug/release "should" behave so differently?


Solution

  • You've violated the one definition rule — your program contains two definitions of foo<float>::init.

    One definition occurs in the compilation unit foo_float.cpp, and the other appears in the compilation unit main.cpp.

    Violating the one definition rule means undefined behavior — in this case, what likely happens is:

    • With optimizations off, the program generates an actual function call, and the linker happened to put foo_float.cpp's version of the function in the executable.
    • With optimizations on, when compiling main.cpp the compiler inlined the function — naturally, it would inline main.cpp's version of the function.