静态变量不会被初始化

时间:2017-03-23 13:22:15

标签: linux gcc rhel7

我们正试图从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;
}

在作为util_Registry的d_selfsIntents上调用find(const OTC_String&amp; name)会导致核心转储,因为d_selfsIntents尚未初始化。

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

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

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

谢谢你,
sglasgow

1 个答案:

答案 0 :(得分:1)

我想念的一个问题是你是否尝试在其他静态数据成员初始化期间或执行已经进入main之后访问这些静态数据成员。

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

可能有一些技巧需要改进,但处理这种情况的常用方法是在静态方法中完成初始化,这些方法充当这些成员的公共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;
}