【问题标题】:C++ static variable in .lib does not initialize.lib 中的 C++ 静态变量未初始化
【发布时间】:2014-05-22 04:11:25
【问题描述】:

我在 VS2010 中有静态库 (.lib) 并将其链接到我的测试项目。

该库有一个我使用以下 MACRO 创建的工厂:

#define REGISTER_FACTORY(mType, my_class) \
class Factory##my_class : public CAbstractFactory\
{\
public:\
    Factory##my_class() : CAbstractFactory(mType){}\
    CBaseClass *Create()\
    { return new my_class(); }\
};\
static Factory##my_class StaticFactory##my_class;

应该发生的是,在 CAbstractFactory 中,新工厂由mtype 注册。但是当我检查工厂时,工厂并不存在。

当我使用 DLL 而不是 .lib 时,它可以正常工作。我的猜测是链接器不包含静态变量,因为它没有被引用,或者静态变量甚至没有包含在库中。

如何强制链接器在我的 .exe 中包含静态库中的所有对象。

我是这样使用宏的:

// Register factory that can create CMyObject with ID=100
REGISTER_FACTORY(100, CMyObject);

class CMyObject
{
};

CAbstractFactory 如下所示:

class CAbstractFactory {
    CAbstractFactory(int id) {
        CFactory::instance().add(id, this);
    }
}

然后是代码中的其他地方,我使用的主 .exe:

CBaseClass *pObject = CFactory::instance().Create(100);

这会给我一个新的CMyObject。这个想法是我有许多不同种类的对象,并且我有一个数据库,其中包含指定我需要的对象种类的 id。 100 只是一个例子。

确实,我没有直接从 .lib 中引用任何东西,但我希望能够使用我的工厂创建对象

CFactory 类是一个简单的类,它保存所有 CAbstractFactory 类的寄存器(在映射中)并将 create 方法委托给正确的工厂。

CFactory &CFactory::Instance()
{
    static CFactory instance;
    return instance;
}

主要问题在于我没有从 .lib 中引用任何内容,因为这一切都是通过 CFactory 完成的。如果我将其设为 DLL 并确保添加对该 DLL 的一些引用以确保它已加载,则它会起作用。但是对于 .lib,我什至添加了一个虚拟函数,以确保我至少有一个不包含其余代码的引用。

【问题讨论】:

  • 这只是一个宏,希望你用在什么地方。
  • 是的,我用它来为一系列对象创建工厂。我添加了更多细节。
  • 显示CFactory::instance() 的定义(以及任何引用的内容)。看起来它可能正在返回对静态对象的引用
  • 添加了CFactory::instance(),确实是静态的,但是CFactory在不同的DLL中。
  • “CFactory 存在于不同的 DLL 中” - 哦。我不确定其他 DLL 中的静态对象应该如何工作,希望其他人可以帮助您

标签: c++ visual-studio-2010 dll static-libraries static-members


【解决方案1】:

我遇到了类似的问题,并通过将 lib 项目设置为主应用程序项目的依赖项,然后将主项目的“链接库依赖项”和“使用库依赖项输入”设置为“是”来解决它。


更新:

最近我发现 Visual Studio 2015 现在支持 /WHOLEARCHIVE 链接器标志。我无法通过链接器选项找到它,但您可以将其添加为额外的命令行选项。它的工作方式类似于 GCC 标志 -whole-archive 并将其添加到目标链接器标志(而不是静态库标志)。

例如,将/WHOLEARCHIVE:lib_name 指定为附加的链接器命令行选项,它将包含该库中的所有符号。您也可以在多个库中执行此操作。

如果您使用此/WHOLEARCHIVE:lib_name,则不再需要将“链接库依赖项”和“使用库依赖项输入”设置为“是”。这非常适合通过 CMAKE 生成的解决方案。在此处查看相关答案:https://stackoverflow.com/a/42083877/1151329

【讨论】:

  • 现在我已经手动配置了 Input ` Additional Dependencies` 中的 .lib 和 Additional Library Directories 中的路径。我可以从 .lib 访问虚拟函数,但未初始化静态。我还将库添加到Project Dependencies。我应该采取不同的做法吗?
  • 您的主应用程序的“链接器->常规->链接库依赖项”和“链接器->常规->使用库依赖项输入”是否设置为“是”?
  • 知道了。我手动将lib链接到mainapp。我应该这样做:MainProject->Properties->Common Properties->Framework and References,然后添加我的 Lib 作为参考。与您描述的选项一起完成了这项工作!
  • 同时检查您是否将“链接器->优化->参考”设置为“否 (/OPT:NOREF)”
  • 现在看看我是否也可以使用 CMake 让它工作;)
【解决方案2】:

static 定义了一个具有内部链接的对象 --> 如果它没有在同一翻译单元中在内部 使用,则可以对其进行优化。从您的实例化中删除 static 以使对象具有外部链接 - Factory##my_class StaticFactory##my_class;

【讨论】:

  • 我不想直接链接到静态。我希望它实例化并向我的工厂注册。
  • @icepack 基类构造函数调用该单元之外的函数,因此应该防止它被优化
  • @Matt McNabb,我在 GoogleTest 网站的某处读到,他们警告说 VC++ 编译器/链接器中存在错误,它确实优化了不应优化的代码。我想这对于非常依赖这种机制的测试套件来说是一个真正的问题。见code.google.com/p/googletest/wiki/…
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-10-26
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多