Windows C++静态库在初始化期间无法访问外部方法

Windows C++ static library fails to access external method during initialization

本文关键字:访问 外部 方法 静态 C++ 初始化 Windows      更新时间:2023-10-16

我正在将一个大型Windows C++应用程序从一组大型源文件转换为一个较小的核心应用程序,链接到几个静态库(许多移动原始源文件的(。

每个库都需要访问核心应用程序中的"注册方法"。每个库都应该在全局初始化期间调用该方法,但没有发生。这是我的问题。

在不使用库的原始形式中,代码运行良好。我想我省略了库的必要链接选项,但是我不知道是哪一个。

我创建了一个最小的、可行的例子。我开发了这个在Windows 10上使用:

CMake 3.14.5
MSVC 2019

这里是CMakeLists.txt:

cmake_minimum_required(VERSION 2.8.9)
project (CMakeLinkTest)
add_library(myLibrary STATIC MyStar.cpp)
add_executable(CMakeLinkTest StarFactory.cpp main.cpp)
target_link_libraries(CMakeLinkTest myLibrary)

该应用程序包含main.cpp:

#include <iostream>
int main(int argc, char *argv[]){
std::cout << "Hello World!" << std::endl;
return 0;
}

以及一个名为StarFactory的单例类。

StarFactory.h:

#include<string>
class StarFactory
{
public:
static StarFactory* instance();
~StarFactory() {};
std::string registerStarType(std::string a_type);
private:
StarFactory() {};
static StarFactory* mp_instance;   // Singleton instance 
};

StarFactory.cpp:

#include <iostream>
#include "StarFactory.h"
StarFactory* StarFactory::mp_instance = 0;
StarFactory* StarFactory::instance()
{
if ( mp_instance==0 )
mp_instance = new StarFactory;
return mp_instance;
}
std::string StarFactory::registerStarType(std::string a_type)
{
std::cout << "registerStarType: " << a_type << std::endl;
return a_type;
}

最后,一个静态库包含类MyStar,该类使用全局初始化时的singleton。

MyStar.cpp:

#include<string>
#include "StarFactory.h"
class MyStar
{
public:
MyStar() {
StarFactory* s = StarFactory::instance();
//s->registerStarType("MyStar");
};
};
MyStar myStar;
std::string starName = StarFactory::instance()->registerStarType("MyStar");

现在看看会发生什么。如果我将MyStar.cpp直接链接到应用程序中,我会看到:

>CMakeLinkTest.exe
registerStarType: MyStar
Hello World!

如果将MyStar.cpp链接到MyLibrary.lib并将其链接到我看到的应用程序:

>CMakeLinkTest.exe
Hello World!

因此,库对应用程序的singleton的调用(MyStar.cpp的最后一行(不起作用。

有人能解释一下吗?

正如engf-010所说,如果不使用静态库中定义的符号,链接器将不会将其放入最终的二进制文件中。

使用CMake解决问题的一种方法是使用OBJECT库而不是STATIC库。

链接器的默认行为是不包括未被引用的静态库。

您可以:

  • 强制链接器包含库-您可以使用cmake的add_link_options或等效程序
  • 不使用静态库-只需像第一个示例中那样链接对象
  • 引用静态库中的代码
  • 改为使用共享对象(动态库(