【问题标题】:Are file scoped static objects zero initialized before static initialization occurs for the owning translation unit?文件范围内的静态对象是否在所属翻译单元发生静态初始化之前初始化为零?
【发布时间】:2013-10-29 12:45:34
【问题描述】:

在文件maybe_use_foo.cpp中:

namespace {
    class Foo { /* ... */ };
    Foo* const the_foo = new Foo;
}

void funtion_callable_from_another_tu_during_process_wide_initialization() {
    // If we haven't yet run static initialization for this TU,
    // but some other static initializer called us, ignore the request.
    if (!the_foo)
      return;

    // OK, static initializers for this TU have run, foo exists, use it.
    the_foo->doSomething();
}

那么,无论上述是否可取,它总是有效吗?在我看来,它假设在 TU 的静态初始化运行之前静态初始化为零。 C++ 标准(C++03?C++11?)能保证吗?

另一种提问方式是询问当解释为 Foo* 时,哪些值序列保存在“the_foo”的存储中。肯定是{NULL/nullptr, new Foo},还是{undefined, new Foo},还是别的什么?

请不要建议其他组织方式:我不是在寻找如何更好地做到这一点的建议,我是在寻找对技术合法性的更深入了解。

【问题讨论】:

    标签: c++ static initialization standards


    【解决方案1】:

    C++11

    [basic.start.init]/2

    具有静态存储持续时间 (3.7.1) 或线程存储持续时间 (3.7.2) 的变量应在进行任何其他初始化之前进行零初始化 (8.5)。

    [...]

    零初始化和常量初始化合称为静态初始化;所有其他初始化都是动态初始化。静态初始化应在任何动态初始化发生之前执行。

    也就是说,是的,变量是零初始化的,但是不,它们不是零初始化静态初始化之前(但作为静态初始化的一部分)。


    OP 中的函数只会在动态初始化期间被调用,因为它不会在零初始化期间被调用,并且必须是 constexpr 函数才能成为常量初始化的一部分。

    【讨论】:

    • 等等Loki loki(5); 在使用构造函数动态初始化之前是零初始化的。构造函数不是constexpr。所以不符合constant-initialization
    • @LokiAstari 从语义上讲,即使是常量初始化的非局部变量也会首先进行零初始化。是的,类类型的非局部变量也将被零初始化,但这意味着(对于非联合类型)每个成员(和填充)的递归零初始化。本质上, .bss 但是,在某些情况下(“如果它没有破坏任何东西”),也可以在编译时应用常量甚至动态初始化,这会将其放在 .data 段中。
    • 好的。现在看看。零初始化不需要构造函数。它只是将内存归零。
    【解决方案2】:

    是的,C++03 标准在 [basic.start.init] 中有解释:

    具有静态存储持续时间 (3.7.1) 的对象应在任何其他初始化发生之前进行零初始化 (8.5)。

    8.5.1 说明:

    对 T 类型的对象进行零初始化意味着:

    ——如果T是标量类型(3.9),则将对象设置为0(零)转换为T的值;

    [..]

    【讨论】:

      【解决方案3】:

      您的代码可能会导致错误。链接器通常不会尝试深入理解单独模块中的初始化部分。最好通过静态函数提供变量,例如

      namespace {
          Foo* the_foo() {
              static Foo* g_ = new Foo;
              return g_;
          }
      }
      

      【讨论】:

      • 正如我在问题中提到的,我不打算重新组织此代码(如果有的话)。我试图了解以上述模式编写的现有代码是否已定义行为。
      • @acm:是的,很抱歉 - 不是很有用 - 评论。
      猜你喜欢
      • 2013-07-21
      • 1970-01-01
      • 2018-01-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多