Search code examples
c++global-variablescompilationunit

Using a global variable to initialize other global variable in different compilation units


I have a shared library which exports a function that returns a string from a global variable like so:

test.h:

const std::string &test_get_name();

test.cpp:

static std::string name = "Test";
const std::string &test_get_name() {return name;}

In my main program (which links against the shared library), I define a global variable (is it still called a 'global' variable if it's static?) which uses that function to initialize an object:

main.cpp:

#include "test.h"
#include <iostream>
struct TestStruct
{
    std::string value;
};
static TestStruct v{test_get_name()};

int main(int argc,char *argv[])
{
    std::cout<<v.value<<std::endl;
    return 0;
}

As far as I understand it, this should be undefined behavior, because the variable 'name' is not necessarily initialized yet when the struct object is created, is that correct? If so, would it be valid if I moved the 'name' variable inside "test_get_name"?:

const std::string &test_get_name()
{
    static std::string name = "Test";
    return name;
}

Solution

  • Your second method will work (the first is not safe), but it will cost you a threadsafe initialiser. This has minimal runtime overhead but it does generate quite a lot of code, see at Godbolt.

    If that bothers you, the code generated by this function doesn't seem to be too bad (both gcc and clang construct the temporary inline):

    const std::string test_get_another_name()
    {
        return "Test 2";
    }
    

    And then of course, static TestStruct v{test_get_another_name()}; is safe.

    You will find both test_get_name and test_get_another_name in the Godbolt link above so you can compare the code generated by the two functions.