【问题标题】:Problem facing with multiple instance of signleton due to static library由于静态库而面临多个单例实例的问题
【发布时间】:2011-09-08 13:04:21
【问题描述】:

在以下场景中,我们的模块之一面临一个静态变量问题:

我有一个单例类“Common”并创建了它的静态库 libcommon.a

//common.h    
class Common
{
    public:
            Common();
            ~Common();
            void Show();
};

//common.cpp
Common::Common()
{cout<<"inside Common::Common"<<endl;}

Common::~Common()
{cout<<"inside Common::~Common"<<endl;}

void Common::Show()
{
    static Common self;
    cout<<"Address of self - "<<&self<<endl;
}

编译:

g++ -ggdb -Wall -fPIC -c common.cpp
ar -cvq libcommon.a common.o

上面的库静态链接了两个动态库“libfirst.so.1.0”&“libsecond.so.1.0”:

//first_so.cpp
#include "common.h"
void run_first_function()
{
    Common c;    
    c.Show();
}

g++ -ggdb -Wall -fPIC -c first_so.cpp

g++ -ggdb -shared -o libfirst.so.1.0 first_so.o -L。 -lcommon

//second_so.cpp
#include "common.h"
void run_second_function()
{
    Common c;
    c.Show();
}

g++ -ggdb -Wall -fPIC -c second_so.cpp

g++ -ggdb -shared -o libsecond.so.1.0 second_so.o -L。 -lcommon

最后一个test.cpp:

#include <dlfcn.h>
#include <iostream>
using namespace std;

int main(int argc, char **argv)
{
    void *lib_handle, *lib_handle1;
    void (*fn)(void);
    void (*fn1)(void);
    int x;
    char *error;

    lib_handle = dlopen("/perforce/sdudhani/test/linux/libfirst.so.1.0", RTLD_LAZY);
    if ((error = dlerror()) != NULL)
    {
            cerr<<"ERROR dlopen.."<<error<<endl;
            exit(1);
    }
    if (!lib_handle)
    {
            cerr<<"ERROR while loading libfirst.so"<<endl;
            exit(1);
    }

    lib_handle1 = dlopen("/perforce/sdudhani/test/linux/libsecond.so.1.0", RTLD_LAZY);
    if (!lib_handle1)
    {
            cerr<<"ERROR while loading libsecond.so.1.0"<<endl;
            exit(1);
    }

    *(void **)(&fn) = dlsym(lib_handle, "_Z18run_first_functionv");
    if ((error = dlerror()) != NULL)
    {
            cerr<<"ERROR run_first_function.."<<error<<endl;
            exit(1);
    }

    *(void **)(&fn1) = dlsym(lib_handle1, "_Z19run_second_functionv");
    if ((error = dlerror()) != NULL)
    {
            cerr<<"ERROR run_second_function.."<<endl;
            exit(1);
    }

    (*fn)();
    (*fn1)();

    dlclose(lib_handle);
    dlclose(lib_handle1);
    return 0;
}

输出:

Address of self - 0x2ad08d8463c0
Address of self - 0x2ad08da483c0

机器详情:

bash-3.2$ uname -a
Linux www.something.com 2.6.18-128.el5 #1 SMP Wed Dec 17 11:41:38 EST 2008  x86_64 x86_64 x86_64 GNU/Linux
bash-3.2$

我的问题是,由于上述设计,“自我”被创建了两次。只是想知道是否有任何链接器/加载器选项可以让我获得单个 self 实例?

任何人都可以建议我,如何处理此类问题?

谢谢 -Shrinivas

【问题讨论】:

  • 光是标题就值金!单例的多个实例:D

标签: c++ static-libraries


【解决方案1】:

静态在 c++ 模块中是唯一的。 c++ 模块是链接单元,在您的情况下,每个动态库都是一个模块。

您需要定义希望单例存在于哪个动态库中。 然后,该库应该具有其他库引用的静态函数或变量。

如果您需要每个库独立运行,但有时要共享一个静态库(一起使用时),请考虑为每个库添加一个设置函数。此函数应在应用程序生命周期的早期调用。该函数会将每个库中的本地静态访问器指向其中一个库中的共享静态访问器。

【讨论】:

    【解决方案2】:

    您还没有将您的 Common 类实现为单例。改为这样做

    //common.h    
    
    class Common
    {
        public:
                ~Common();
                void Show();
                static Common* Instance(); 
        private:
                Common();  --must be private or else multiple instances can be created!
                static Common* m_pInstance
    
    };
    
    //common.cpp
    
    Common* Common::m_pInstance = NULL
    
    Common* Common::Instance()  
    {  
        if (!m_pInstance)   // Only allow one instance of class to be generated.  
           m_pInstance = new Common;  
    
        return m_pInstance;  
    }  
    
    .....
    

    然后,不是像以前那样创建 Commons,而是像这样获得实例:

    //first_so.cpp        
    #include "common.h"        
    void run_first_function()        
    {            
        Common::instance().Show();        
    }   
    

    ...等等..

    【讨论】:

    • Stevie,关于我没有在 common.cpp 中实现的问题“Singleton”的错误。但我的意图只是询问任何静态变量的行为,无论是 Show() 函数中的“self”还是上述场景中 Instance() 函数的“m_pInstance”。或者可以考虑在 Common()(构造函数)中定义“静态 Common self”。
    • 在这种情况下,看看this
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-02-03
    • 2015-08-28
    • 2010-11-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多