外部链接变量多次初始化

时间:2014-08-27 14:10:40

标签: c++ gcc external-links

我有一个合成的例子,有我想改变的行为,但不太了解。

我拥有的是:

  1. 具有某些变量外部声明的公共标题 statich.h

    #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. 从源文件 statich.cpp 编译的静态库 libstatic.a ,它具有该外部变量的定义:

    #include "statich.h"
    
    S nakedS;
    
  3. 动态库 libdyn.so 从源文件 dyn.cpp 编译并链接到 libstatic.a 。这是源代码:

    #include "statich.h"
    
    void foo() {
      std::cout << "I'm foo() from dyn! nakedS.x == " << nakedS.x << std::endl;
    }
    
  4. 可执行 supertest ,从源文件 main.cpp 编译并链接到两个库,静态和共享。这是源代码:

    #include "statich.h"
    int main() {
      std::cout << "nakedS.x == " << nakedS.x << std::endl;
    }
    
  5. 我有 CMakeLists.txt 文件,可以为我构建所有内容。这是:

    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} )
    
  6. 点是,当我运行cmake . && make && ./supertest时,我得到了这个输出:

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

    这意味着同一对象的双重初始化,这根本不是我想要的。我是否可以在不使用静态模拟替换 libdyn.so 的情况下更改此行为?也许,一些编译器/链接器标志?我应该阅读什么来了解更多信息?任何帮助将不胜感激。

    另外,我在我的特定编译器版本上遇到了这种行为: gcc版本4.4.7 20120313(Red Hat 4.4.7-4)(GCC)

    在我有不同编译器的其他机器上: gcc版本4.6.4(Ubuntu / Linaro 4.6.4-1ubuntu1~12.04) 一切正常。

    提前致谢!

1 个答案:

答案 0 :(得分:2)

这是预期的行为。要解决这个问题,您可以将变量定义为弱,例如

#include "statich.h"

__attribute__((weak)) S nakedS;