Reputation: 1
We are attempting to move from RHEL 6.7 to RHEL 7.3 and from gcc 4.4.7 to gcc 4.8.5.
None of our static variables (initialized outside of class definitions) get initialized. Example, in file unitprot_selfsintent.cc:
util_Registry<unitprot_SelfsIntent> * unitprot_SelfsIntent::d_selfsIntents =
new util_Registry<unitprot_SelfsIntent>();
d_selfsIntents is declared static in unitprot_selfsintent.h.
util_Registry is a template class. The first time we attempt to place something in this registry the application core dumps. d_selfsIntents is a 0 pointer and has not been initialized.
I would have thought that this would have been accomplished long before we ever tried to place something in the registry.
Everything works as it should under the old configuration. What might have changed to cause this in the new configuration. Is there a new compiler option I need to invoke?
More information...
Another class, unit_groundresunitc2.cc, has a static variable defined as follows:
static unitprot_Selfintent * f_en_route_to_escort =
unitprot_SelfsIntent::registerObject("en_route_to_escort");
unitprot_SelfsIntent::registerObject looks like this:
unitprot_SelfsIntent * unitprot_SelfsIntent::registerObject(const char * si)
{
OTC_String selfsIntent(si);
return registerObject(selfsIntent);
}
The call to registerObject with an OTC_String is as follows:
unitprot_SelfsIntent * unitprot_SelfsIntent::registerObject(const OTC_String & si)
{
unitprot_SelfsIntent * regObj = d_selfsIntents->find(si);
if (regObj == 0)
{
regObj = new unitprot_SelfsIntent(si);
d_selfsIntents->registerObject(regObj);
}
return regObj;
}
Calling find(const OTC_String & name) on d_selfsIntents which is a util_Registry causes a core dump because d_selfsIntents has not been initialized.
So to answer Matteo's question, yes we are trying to access a static construct (d_selfsIntents) from the initialization of another static construct (f_en_route_to_escort).
I see the problem with using one before the other is initialized. A question I might have is why is this now a problem? His suggestion sounds like something that should have been dealt with long ago. Our code has hundreds of examples like this and has been in development for over 15 years, and has never been a problem until now.
What sets the order, the compiler or the linker? The two compilation units in question here is unitprot (for unitprot_SelfsIntent) and util (for util_Registry). We do compile them in a specific order, but I think the problem is occurring either at link time or at runtime.
Thank you,
sglasgow
Upvotes: 0
Views: 169
Reputation: 344
Something I miss from the question is whether you try accessing these static data members during other static data members' initialization or after the execution has already entered main.
If it's the first case, please note that static initialization of variables is not guaranteed to happen in any specific order, relative to those defined in different compilation units.
There might be tricks to improve on that, but the usual way to handle this is to have the initialization done inside static methods that act as public getters for those members. Simplified, this amounts to using the singleton pattern.
Your example would then look like this in the header:
class unitprot_SelfsIntent : ...
{
public:
static util_Registry<unitprot_SelfsIntent>* GetSelfsIntents();
//...
private:
static util_Registry<unitprot_SelfsIntent>* d_selfsIntents;
//...
};
And your implementation something like:
util_Registry<unitprot_SelfsIntent>* unitprot_SelfsIntent::GetSelfsIntents()
{
// usually multithreading would be handled here
d_selfsIntents = new util_Registry<unitprot_SelfsIntent>();
// some more synchronization
return d_selfsIntents;
}
Upvotes: 1