Search code examples
c++initializationglobal-variablesstatic-librariesstatic-linking

C++ global variable not initialized when linked through static libraries, but OK when compiled with source


I have created a system that automatically registers function objects (functors) into a map based on the constructor of an global instance.

In each cpp file that defines the functor, there's a global instance of the registrar class instance to register the functor to a singleton std::map<int, std::function<...> > object.

This is the definition of registrar class:

template
<
    typename map_type,
    typename handler_type
>
struct registrar
{
    registrar
        (
             map_type& map_object,
             boost::uint16_t cmd_code,
             const handler_type& handler
        )
        {
          map_object.insert(std::pair<boost::uint16_t, handler_type>(cmd_code, handler));
        }
};

in each .cpp file. The global instance is defined like this:

namespace one_way
{
    static registrar <in_out_map_type, handler>
        post_receiver(in_out_map_type::instance(), command, handlers());
}

All works fine if I compile all the cpp with the main.cpp together. But If I compile the cpp file into a static library and link it to main.cpp, the registration does not work.

I tested with VC10 and GCC4.61 both on Windows & and Ubuntu 11.10. Both fail.

I found a thread with the same problem but OP did not say whether he solved it or not.

Am I missing anything?


Edit


Thanks for all responses including the comments.

Every response indeed helped me to think more and investigate deep into this method. After all the study and trials, I finally gave up the idea of relying on global/static variable for self-registration across binary boundaries, because there's no portable way to guarantee it will work.

My final way is to keep the registration within one binary.


Solution

  • I believe your object file from the library is not getting linked. Look how Microsoft handles the acrtused symbol (search case insensitive, I do not remember the case and there's no MSVC on this machine).

    Once you know how they handle acrtused, do the same thing with your global variable to force it to get linked.

    Will update if I find the answer.

    Here are a couple of possibilities to force things to link and initialize in a somewhat forced order.

    Look here for a GCC answer.

    Look here for MSVC10.