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

415 Views Asked by At

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

There are 2 best solutions below

0
Paul Sanders On BEST ANSWER

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.

0
Bo Persson On

The static variable inside the function will be initialized the first time the function is called, so yes it will work.

For things other than a string, like a class with more side effects, there might be a difference as if the function is not called, the object will never be constructed at all.