2017-03-23 125 views
0

我们正试图从RHEL 6.7迁移到RHEL 7.3,并从gcc 4.4.7迁移到gcc 4.8.5。静态变量未初始化

我们的静态变量(在类定义之外初始化)都没有初始化。例如,在文件unitprot_selfsintent.cc:

util_Registry<unitprot_SelfsIntent> * unitprot_SelfsIntent::d_selfsIntents = 
    new util_Registry<unitprot_SelfsIntent>(); 

d_selfsIntents声明中unitprot_selfsintent.h静态的。

util_Registry是一个模板类。我们第一次尝试在这个注册表中放置某些东西时,应用程序内核就会转储。 d_selfsIntents是一个0指针,尚未初始化。

我原以为这会在我们尝试在注册表中放置某些东西之前就已经完成了。

一切正常,因为它应该在旧的配置下。什么可能已经改变,导致新的配置。是否有我需要调用的新编译器选项?

更多信息...

另一类,unit_groundresunitc2.cc,具有已定义的静态变量如下:

static unitprot_Selfintent * f_en_route_to_escort = 
    unitprot_SelfsIntent::registerObject("en_route_to_escort"); 

unitprot_SelfsIntent :: registerObject看起来是这样的:

unitprot_SelfsIntent * unitprot_SelfsIntent::registerObject(const char * si) 
{ 
    OTC_String selfsIntent(si); 
    return registerObject(selfsIntent); 
} 

使用OTC_String调用registerObject如下:

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

在d_selfsIntents(它是util_Registry)上调用find(const OTC_String &名称)会导致核心转储,因为d_selfsIntents尚未初始化。

因此,要回答Matteo的问题,是的,我们试图从另一个静态构造(f_en_route_to_escort)的初始化中访问静态构造(d_selfsIntents)。

我看到使用一个之前,其他人被初始化的问题。我可能会遇到的问题是为什么现在这是一个问题?他的建议听起来像是早就应该处理的事情。我们的代码有数百个这样的例子,并且已经开发了超过15年,直到现在从未成为问题。

什么设置顺序,编译器或链接器?这里讨论的两个编译单元是unitprot(用于unitprot_SelfsIntent)和util(用于util_Registry)。我们按特定顺序编译它们,但我认为问题发生在链接时或运行时。

谢谢
sglasgow

+0

谷歌*静态初始化顺序的悲剧*。一开始你很幸运​​,但现在运气已经用完了。这就是人生。 –

回答

1

我的东西从问题怀念的是你是否尝试在其他静态数据成员的初始化或执行已经进入主后访问这些静态数据成员。

如果是第一种情况,请注意,变量的静态初始化不保证以任何特定顺序发生,相对于在不同编译单元中定义的顺序。

可能有一些技巧可以改善这一点,但通常的处理方法是在静态方法中完成初始化,这些静态方法充当这些成员的公共getter。简单来说,这相当于使用单例模式。然后

你的榜样应该是这样的标题:

class unitprot_SelfsIntent : ... 
{ 
public: 
    static util_Registry<unitprot_SelfsIntent>* GetSelfsIntents(); 
//... 
private: 
    static util_Registry<unitprot_SelfsIntent>* d_selfsIntents; 
//... 
}; 

以及实现这样的:

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