Search code examples
c++gccexternal-links

external linked variable initialized multiple times


I have a little synthetic example that have behaviour I want to change, but don't quite know how.

What I have is this:

  1. Common header statich.h that have external declaration of some variable:

    #include <iostream>
    struct S {
      S() : x(42) { 
        std::cout << "S(), this=" << this << std::endl;
      }
      ~S() { 
        std::cout << "~S(), this=" << this << std::endl;
      }
      int x;
    };
    
    extern S nakedS;
    
  2. Static library libstatic.a compiled from source file statich.cpp, that have definition of that external variable:

    #include "statich.h"
    
    S nakedS;
    
  3. Dynamic library libdyn.so compiled from source file dyn.cpp and linking with libstatic.a. Here's source code:

    #include "statich.h"
    
    void foo() {
      std::cout << "I'm foo() from dyn! nakedS.x == " << nakedS.x << std::endl;
    }
    
  4. Executable supertest that compiled from source file main.cpp and linking with both of libraries, static and shared. Here's source code:

    #include "statich.h"
    int main() {
      std::cout << "nakedS.x == " << nakedS.x << std::endl;
    }
    
  5. I have CMakeLists.txt file that build all that stuff for me. Here it is:

    cmake_minimum_required(VERSION 2.8.12)
    set(CMAKE_CXX_FLAGS
      "${CMAKE_CXX_FLAGS} -fPIC"    
    )
    
    add_library( static STATIC "statich.cpp" )
    
    add_library( dyn SHARED "dyn.cpp" )
    target_link_libraries( dyn static )
    
    add_executable( supertest main.cpp )
    
    set(DEPS
      static
      dyn
    )
    
    target_link_libraries( supertest ${DEPS} )
    

Point is, when I run cmake . && make && ./supertest I got this output:

S(), this=0x6012c4
S(), this=0x6012c4
nakedS.x == 42
~S(), this=0x6012c4
~S(), this=0x6012c4

Which means double initialization of same object, that is not what I want at all. Can I change this behaviour without replacing libdyn.so with static analogue? Maybe, some compiler/linker flags? What should I read to learn more about it? Any help would be appreciated.

Also, I got this behaviour on my specific compiler version: gcc version 4.4.7 20120313 (Red Hat 4.4.7-4) (GCC)

On other machine where I have diffirent compiler: gcc version 4.6.4 (Ubuntu/Linaro 4.6.4-1ubuntu1~12.04) All works fine.

Thanks in advance!


Solution

  • This is expected behaviour. To work it around, you could define your variable as weak, e.g.

    #include "statich.h"
    
    __attribute__((weak)) S nakedS;