Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

cpp file with a single global variable is ignored

I'm trying to initialize a global map

std::map<long, std::string> Global_ID_Mapper;

with a number of "init" classes like:

struct AGlobalMapperInitializer
{
    AGlobalMapperInitializer() 
    {
        Global_ID_Mapper.insert( std::make_pair(1, "Value1") );
        Global_ID_Mapper.insert( std::make_pair(2, "Value2") );
    }
};

I want to fill the map automatically during application start. So in one of my cpp files, I just define a global variable of that "init" class.

// AGlobalMapperInitializer.cpp

AGlobalMapperInitializer AGlobalMapperInitializer_Value;

The Mapper filling is a side effect of the AGlobalMapperInitializer_Value creation.

The problem is that the cpp is obviously ignored by linker if the cpp doesn't contain anything except this global variable. When I put some useful other code into the cpp (or define the global initializer in some non-empty cpp), the constructor is invoked and the global mapper is filled. But if the cpp contains only the global that isn't referenced in no other file, the cpp is compiled, the obj file contains the variable, but the linker doesn't mention it during the link and it is missed in the exe.

How can I insist on linking the cpp into exe? Is there some pragma or dummy code to put into the cpp to get it non-ignored? I use the Visual Studio 2012.

like image 473
Kunis Avatar asked Feb 02 '26 07:02

Kunis


2 Answers

C++ does not require initialisation of a global variable x to take place if no function or variable from the same file (actually translation unit) as x is ever referenced.

See C++11 [basic.start.init]§4:

It is implementation-defined whether the dynamic initialization of a non-local variable with static storage duration is done before the first statement of main. If the initialization is deferred to some point in time after the first statement of main, it shall occur before the first odr-use (3.2) of any function or variable defined in the same translation unit as the variable to be initialized.

So to force the variable initialisation, you have to put it into a file whose other contents you actually use, or directly use the variable somewhere.

like image 194
Angew is no longer proud of SO Avatar answered Feb 04 '26 20:02

Angew is no longer proud of SO


The linker doesn't include the variable and it's initializer when it is not referenced. You can create a reference to this variable inside your code:

int main()
{
    printf("", &AGlobalMapperInitializer_Value));
}

If you want to avoid this contamination of the source code you cause the same effect with the /INCLUDE argument of the linker. You have to add the decorated name that you can take from the .map file when you have tried the hack above.

The VS2010 offers this options as Force Symbol Reference in the project properties: Configuration Properies -> Linker -> Input. I hope it's the same for VS2012.

like image 41
harper Avatar answered Feb 04 '26 21:02

harper



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!