【问题标题】:Static variable initialization over a library库上的静态变量初始化
【发布时间】:2011-07-09 07:08:52
【问题描述】:

我正在开发一个将添加类型的工厂,但是,如果该类未在执行的 .exe 中显式启动(编译时),则该类型不会添加到工厂中。这是因为静态调用在某些方面没有进行。有人对如何解决这个问题有任何建议吗?下面是我放入一个库的五个非常小的文件,然后一个 .exe 将调用这个库。如果有任何关于如何让它工作的建议,或者更好的设计模式,请告诉我。这基本上就是我要找的东西

1) 可以接受类型的工厂

2) 自动注册进入classes .cpp 文件,任何和所有注册码都应该进入class .cpp(下面的例子,RandomClass.cpp)而不是其他文件。

BaseClass.h : http://codepad.org/zGRZvIZf

RandomClass.h : http://codepad.org/rqIZ1atp

RandomClass.cpp:http://codepad.org/WqnQDWQd

模板工厂.h:http://codepad.org/94YfusgC

模板工厂.cpp:http://codepad.org/Hc2tSfzZ

【问题讨论】:

    标签: c++ static-libraries static-linking


    【解决方案1】:

    当您与静态库链接时,实际上是从中提取提供当前使用但未定义的符号的目标文件。在您使用的模式中,可能没有由包含触发注册的静态变量的目标文件提供的未定义符号。

    解决方案:

    • 使用显式注册
    • 编译单元提供了一个未定义的符号
      • 使用链接器参数将静态变量添加为未定义符号
      • 有用的东西,但这通常不自然
      • 一个虚拟的,如果它是由主程序提供的,那么它是不自然的,作为链接器参数,它比使用静态变量的重命名更​​容易
    • 使用链接器参数声明必须包含库的所有对象
    • 动态库已完全导入,因此没有这个问题

    【讨论】:

    • "动态库完全导入,所以没有这个问题"。我用 .dll 试过这个,但仍然遇到这个问题。你知道为什么会这样吗?
    • 不知道——但我从来没有假装对 Windows 很了解。
    • @jack:在 DLL 中,问题很可能不是注册函数没有运行,而是他们更新了一个 DLL 私有的注册列表。为此,主应用程序需要查询 DLL 的注册列表,而不是维护自己的列表。
    【解决方案2】:

    作为一般经验法则,应用程序不包含库中的静态或全局变量,除非它们被应用程序隐式或显式使用。

    有一百种不同的方式可以重构它。一种方法是将静态变量放在函数中,并确保函数被调用。

    【讨论】:

    • 有没有像我这样的自动注册,可以吗?
    • 不是 100% 自动的,但如果您以某种方式从应用程序中包含的任何代码或变量中添加对静态变量的引用,它将起作用。
    【解决方案3】:

    为了扩展@AProgrammer 的一个优秀建议,这里有一种可移植的方式来保证调用程序将引用库中的至少一个符号。

    在库代码中声明一个返回int的全局函数。

    int make_sure_compilation_unit_referenced() { return 0; }
    

    然后在库的 header 中声明一个 static 变量,该变量通过调用全局函数来初始化:

    extern int make_sure_compilation_unit_referenced();
    static int never_actually_used = make_sure_compilation_unit_referenced();
    

    每个包含头文件的编译单元都会有一个静态变量,需要通过调用库中的(无用的)函数来初始化。

    如果您的库有自己的命名空间来封装这两个定义,这会变得更简洁一些,那么您库中的虚假函数与其他库或静态变量与包含标头的编译单元。

    【讨论】:

      猜你喜欢
      • 2011-08-22
      • 2010-12-22
      • 1970-01-01
      • 2010-12-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多