单列模板类跨dll调用异常处理

多个动态库引用实例化单例模板类,出现静态变量地址不一致问题
问题描述
主要原因:
解决办法
问题描述
我们在base.dll中定义了一个单例模板类,并同时对这个模板类进行实例化。在A.dll和B.dll中分别引用了base.dll的头文件,当进程进程启动时,我们发现A.dll中的这个实例化的单例类的静态成员变量的地址与B.dll中的地址不一致。理论上同一个实例化的类的静态成员变量地址都位于全局区域,且地址一致。

base.dll 中base.h
template<class Base>
    class Singleton
    {
    public:
        Singleton(const Singleton&) = delete;
        Singleton& operator=(const Singleton&) = delete;
        virtual ~Singleton(){}
    private:
        inline static Singleton&getInstance() {
          static Singleton instance;
          return instance;
        }
        Singleton(){}
    };
class DataManager;
using DataManagerFactory=Singleton<DataManager>;   

A.dll中引用了base.h
#include <base.h>
void print(){
auto& ref = DataManagerFactory::getInstance();
}

B.dll中也引用了base.h
#include <base.h>
void print(){
auto& ref = DataManagerFactory::getInstance();
}

当程序同时应用了A.dll和B.dll时,我们发现通过DataManagerFactory::getInstance()获取的地址不一致

主要原因:
虽然我们在base.h中实例化了单例类,但并没有导出,所以就导致在A.dll中引用base.h时,会对这个单例类再次实例化,B.dll中也一样,所以在程序运行期间出现了多个实例,从而导致DataManagerFactory::getInstance()获取的地址不一致。

解决办法
实例化单例模板类时,需要将该类标记为导出类,这样多个动态库引用时就不会重复实例化了。修改后如下:

base.dll 中base.h
#if defined(DLL_EXPORTS)
#define DLL_API __declspec(dllexport)
#else
#define DLL_API __declspec(dllimport)

没有评论: