• C++中模板单例的跨SO(DLL)问题:RTTI,typeid,static,单例


    (转载请注明原创于潘多拉盒子)

    C++的模板可以帮助我们编写适合不同类型的模板类,给代码的复用性提供了极大的方便。近来写了一个涉及单例的C++模板类,简化下来可以归结为以下的代码:

    template <typename T>
    class Singleton
    {
    public:
        // 此处省去了多线程安全锁
        static T* getInstance()
        {
        static T t;
        return &t;
      }
    };
    

      那么如果希望对某个work horse类,比如叫做Foo,定义一个Singleton,就会很容易啦:

    Foo* foo = Singleton<Foo>::getInstance();
    

     注意这里不需要自己释放foo,因为它不是new出来的。

    如果代码被编译成“一个”so(dll)或可执行文件,这里的Singleton得到的对象却是是单例的,也就是说,某一种类型得到的对象地址是确定的。

    但是,如果同一个类型的单例在不同的so(dll,可执行文件)中使用,那么得到的同一个类型的单例对象,其地址也是不一样的。比如

    libfoo.so文件中的如下代码:

    Foo* foo = Singleton<Foo>::getInstance();
    std::type_info fooType = typeid(Singleton<Foo>);
    

      和libbar.so中的另一端代码:

    Foo* bar = Singleton<Foo>::getInstance();
    
    std::type_info barType = typeid(Singleton<Foo>);
    

      其中foo和bar的地址是不同的!他们并不是真正的单例。

    为什么呢?原因是模板是编译的时候实例化成“真正的类”的,而在两个不同的so编译生成的过程中,编译器进行了两个不同的实例化过程,他们被实例化成了不同的类。也不是完全不同,但有部分是不同的。

    比如,对上述两个so,如果去测试两个Singleton类型是否为同一类型(RTTI):

    if (fooType == barType)
    

      那么该测试会返回false。但是,如果测试两个类型的名字是否相等:

    if (strcmp(fooType.name(), barType.name()) == 0)
    

      该测试则会返回true。

    这说明,两个类型虽然type_info不同,但名字却是相同的。

    在Google上搜了一下相关的信息,发现这确实是一个难题。因此,用模板来实现单例,是无法跨so的。当然,这里不是真正用模板来实现单例,只是用这个例子来演示模板的RTTI特性。

  • 相关阅读:
    算法-heapq模块优先队列
    用find命令删除某目录下及所有子目录中某类型的特定文件
    OpenStack虚拟机virtaulinterfance 网络设备在libvirt的代码梳理
    cinderclient命令行源码解析
    python 多个装饰器的调用顺序分析
    wsgi的environ变量
    Cirros镜像
    写入多个变量到配置文件【linux】
    SecureCRT 私钥登录ec2 报:A protocol error occurred.Too many authentication failures for ec2-user 解决
    S3上备份的json文件转存成parquet文件
  • 原文地址:https://www.cnblogs.com/bqzhao/p/3531748.html
Copyright © 2020-2023  润新知