0

I have files that are linked together:

basic.h

#pragma once

extern const string APPLICATION_NAME;

application.cpp

#include "basic.h"

const string APPLICATION_NAME = "MyApplication";

............

ErrorTables.h

class ErrorTable
{
public:
    ErrorTable();

private:
    map <index, errorRecord> _errorTable;


};

ErrorTables.cpp

#include "basic.h"

ErrorTable TheErrorTable;

ErrorTable::ErrorTable()
{
   ...
   _errorTable[errorIndex] = errorRecord(APPLICATION_NAME + " hit some error.");
   ...
}

This code can be built and run OK in Visual Studio. When I use GCC, it can be build but failed in run time. The problem is in TheErrorTable that has static linkage and is created before main() is started; it can't resolve APPLICATION_NAME variable. If I hide it using local variable everything works OK.

Is there a GCC flag that force resolution of a static variable during build time or implements behavior of Visual Studio in some other way?

Anteru
  • 19,042
  • 12
  • 77
  • 121
Yev.
  • 1

1 Answers1

2

The problem is in TheErrorTable that has static linkage and is created before main() is started; it can't resolve APPLICATION_NAME variable.

That's right. Either TheErrorTable or APPLICATION_NAME is initialised first, and you can't fix this.


Make ErrorTable not be a global. You cannot define the order of static initialisation across TUs, and even if you could you'd just be making the code harder to follow.

I hate to say it, but ErrorTable might benefit from the singleton pattern here (because function-statics have sane initialisation order), at least in as much as that it's the solution closest to your existing code.


Update

As @godexsoft alluded to, you can get around this by taking advantage of constant initialisation and making APPLICATION_NAME a char const* rather than a std::string; your initialiser will then be a constant-expression initialiser without a constructor call, and as such will be invoked — across TUs — before any ErrorTable, guaranteed. (Really? Yes.)

Community
  • 1
  • 1
Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
  • +1 I _think_ replacing `APPLICATION_NAME` with a function that returned same string would also correct this? – hmjd Jan 05 '12 at 21:22
  • @hmjd: Yes, that'd do it too, as long as the string were local to that function. That's essentially like making `APPLICATION_NAME` a mini-singleton ;) – Lightness Races in Orbit Jan 05 '12 at 21:24
  • Or just make it char* which will force it to be initialized before any non-PODs (true for static globals). – Alex Kremer Jan 05 '12 at 21:38
  • @godexsoft: Really? I wasn't aware of that. Can you provide a citation? – Lightness Races in Orbit Jan 05 '12 at 21:39
  • @LightnessRacesinOrbit yeah.. I stumbled upon that in the past and remembered ever since :-) I actually can not find a citation.. – Alex Kremer Jan 05 '12 at 21:41
  • @LightnessRacesinOrbit That could be true. I do remember that in my apps changing global constants to char* definitely fixed all problems. That was done after i found somewhere on the web that PODs are being initialized first. I'm not sure if that's global or per compilation unit though. Most likely it's per CU.. and if that's so - the solution is not good. – Alex Kremer Jan 05 '12 at 21:48
  • @godexsoft: I'm pretty sure that's not true whatsoever. Pretty sure you're thinking of _zero-initialisation_, which is a first-step zero-ing for all statics but doesn't give you the initialisation you actually want (and that you ultimately get, at whatever time during normal static initialisation). – Lightness Races in Orbit Jan 05 '12 at 21:49
  • @LightnessRacesinOrbit If you read here: http://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Nifty_Counter i think they employ that rule of PODs being initialized first when they use the counter (static int).. maybe i'm wrong. But i see it's definitely not global - only per compilation unit. – Alex Kremer Jan 05 '12 at 21:52
  • Oh I see what you mean. Yeah.. the counter gets zero-initialized that's for sure. hmmm. I need to find the original post i read at that time.. – Alex Kremer Jan 05 '12 at 21:54
  • @LightnessRacesinOrbit i think i better give up searching and just remember that it's wrong for future :) Cheers for opening my eyes on that! I guess it's implementation dependent and i should never use that anyway.. although for gcc it definitely worked for me (will remove that code :P ) – Alex Kremer Jan 05 '12 at 22:01
  • @godexsoft: You _were_ right; see my updated answer on that other question. :) – Lightness Races in Orbit Jan 06 '12 at 15:17
  • @Lightness Races in Orbit thanks for your help and your time. – Yev. Jan 06 '12 at 19:08