C++ 阻止链接器删除全局变量

C++ 阻止链接器删除全局变量,c++,linker,global-variables,C++,Linker,Global Variables,我使用静态全局变量构造函数作为方便注册函数的技巧,其思想如下: typedef int (*FuncPtr)(int); struct RegHelper { RegHelper(const char * Name, FuncPtr Func) { Register(Name, Func); } } #define REGISTER(func) RegHelper gRegHelper_ ## func (#func, func); 现在我可以通过这

我使用静态全局变量构造函数作为方便注册函数的技巧,其思想如下:

typedef int (*FuncPtr)(int);

struct RegHelper
{
    RegHelper(const char * Name, FuncPtr Func)
    {
        Register(Name, Func);
    }
}

#define REGISTER(func) RegHelper gRegHelper_ ## func (#func, func);
现在我可以通过这种方式注册函数(我使用它来实现某种反射):

问题是,如果我在静态库中使用它,有时链接器会检测到编译单元未被使用,它会删除所有内容。所以全局变量没有被构造,函数也没有被注册


我的问题是:我能做些什么来解决这个问题?在初始化期间在每个编译单元中调用伪函数似乎会触发全局变量的构造,但这并不安全。还有其他建议吗?

是的,我也有这个问题。我找到的唯一解决办法是:

  • 使库成为DLL
或:

  • 将注册对象移动到可执行文件中
这两种方法都不完美,不过如果您不介意使用DLL,DLL解决方案也可以,我也很想知道其他解决方案。

要解决此问题,请:

  • Visual studio(在同一解决方案中):链接器>常规>使用库依赖项输入=是
  • Gcc:直接链接到.o文件
我还没有找到我真正喜欢的解决方案。

请查看

其中有两个关键的重要概念。第一:

(void) register_object;  
使用该对象以确保链接器不会将其剥离

template<typename D> typename automatic_register<D>::exec_register 
    automatic_register<D>::register_object;
然后修改您的register宏,使其成为register(Foo),从而创建:

struct register_Foo : FpList
{
   register_Foo( FuncPtr fn ): FpList(fn)
   {
      (void) register_object;  
   }
   static register_Foo register_object;
};
我认为这还不够。您仍然需要实例化模板,传递if&Foo并确保

register_Foo register_Foo::register_object
实例是在某处创建的。自动_寄存器的模板代码显示了如何在标头中执行此操作。如果可以将宏放在.cxx中,只需声明:

register_Foo register_Foo::register_object( &Foo );

作为宏的一部分。我认为这可能会奏效。(所有这些都来自记忆,谁知道呢)

如果您在UNIX环境中,使用“整个存档”选项调用ld将强制将所有对象文件包括在静态库中,而不考虑其用途。

请参见此处的答案:


这个确实对我有用。其他建议没有。这是解决同一问题的另一种可能的方法。通过函数调用获取常量值。像这样:

常数h

const char blah[10];

extern const char *get_blah();
常数c

#include "header.h"

const char *get_blah()
{ return blah; }

这帮我搞定了

谢谢!这并不是我想要的解决方案,但这已经很有帮助:)我遇到了完全相同的问题,但启用“使用库依赖项输入”对我来说不起作用。我的静态库正在链接到一个Dll,如果这有什么区别的话。我添加了一个新的答案,因为我以不同的方式得到了它。为什么这样做:当编译器看到常量.h时,它要求函数get_blah使用常量.h链接到翻译单元。由于函数位于常量.c中,因此使用整个常量.c.o,而不是像以前那样丢弃。名称
get_blah
在这里没有任何影响,重要的是
extern
技巧
const char blah[10];

extern const char *get_blah();
#include "header.h"

const char *get_blah()
{ return blah; }