2

I am facing one static variable issue with our one of the module in following scenario:

I had an singleton class "Common" and created its static library 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;
}

Compilation:

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

The above library is statically linked with two dynamic libraries "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

Lastly one 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;
}

output:

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

Machine Details:

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$

Here my problem is, "self" is created twice due to above design. Just wanted to know is there any linker/loader options by which i should get single instance of self?

Could any body please suggest me, how to handle such type of problem?

Thanks -Shrinivas

dudhaniss
  • 41
  • 5

2 Answers2

3

Statics are unique within a c++ module. The c++ module is the linked unit, in your case each dynamic library is a module.

You will need to define which dynamic library you want the singleton to live in. That library should then either have a static function or variable that the other libraries refer to.

If you need each libary to function independently but sometimes to share a static (when used together) then consider adding a setup function to each library. This function should be called very early in the application lifetime. The function would point the local static accessor in each library to the shared static in one of the libraries.

morechilli
  • 9,326
  • 7
  • 30
  • 53
0

You havent implemented your Common class as a singleton. Do it like this instead

//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;  
}  

.....

Then, instead of creating Commons like you were, you get the instance like this:

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

...and so on..

StevieG
  • 8,393
  • 20
  • 29
  • Stevie, my mistake about the question "Singleton" which i haven't implemented in common.cpp. But my intention was only to ask about the behavior of any static variable whether it is "self" in Show() function or "m_pInstance" of Instance() function in above mention scenario. Or one can consider "static Common self" to be defined in Common() (constructor). – dudhaniss Sep 09 '11 at 05:52
  • In that case, have a look at [this](http://stackoverflow.com/questions/2479784/exporting-static-data-in-a-dll) – StevieG Sep 09 '11 at 08:41