Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

two instances of a static member, how could that be?

I have a multithreaded application. I declare a class with a static member in a shared library.

Printing the address of the member from different threads from different libraries shows different results.

//declaration

template <class OBJECT>
struct Container
{
   static int m_member;
};

template <class OBJECT>
int Container<OBJECT>::m_member;

// printing

cout << (void*) &Container<int>::m_member << endl;

How could that be?

like image 831
Ezra Avatar asked Jul 26 '12 09:07

Ezra


1 Answers

If you have different libraries, (I'm guessing different dynamic libraries), then you may have some duplication of both code and static variables.

The exact details will depend on the particular dynamic library technology you are using. I'd say that, for example, in Windows DLLs you will have duplicated code and variables, but in Linux SOs you will not.

Anyway, you should give more details on the Operating System and the layout of your project.

UPDATE: Ahh, but your class is a template! Template instantiations in a shared library are a strange beast! To make sure that only one copy of your class is used across all the process you have to explicitly instantiate the template and make sure that this instantiation is exported in the SO, and that it is used from the client code. The details vary with the compiler, but you can check how the std::string is done, for example:

In the header file:

namespace std
{
    extern template class basic_string<wchar_t>;
}

In the source of the library:

namespace std
{
    template class basic_string<wchar_t>;
}

Naturally you need to know in advance which instantiations will be needed of your template. Obviously, the SO cannot export an instantiation that uses a type it knows nothing about.

UPDATE: Ahh, but you have two different libraries instantating the template... then if both libraries define the explicit instantiation as extern the shared ELF magic should merge both instantiations into one.

YET ANOTHER UPDATE: After playing with templates and shared objects, it usually just works. My guess now is that you are compiling the libraries with -fvisibility=hidden or similar. If that is the case, it would be enough just to write:

template <class OBJECT>
struct __attribute__((visibility("default"))) Container
{
   static int m_member;
};

To make the specializations of the template to enter the dynamic symbol table, and thus avoid the duplication.

like image 89
rodrigo Avatar answered Oct 23 '22 03:10

rodrigo