我有C++代码,它声明通过函数调用初始化的静态生存期变量。被调用的函数构造一个vector实例并调用其push_back方法。代码是否会因C++静态初始化顺序的失败而遭受厄运?如果没有,为什么不呢?

补充资料:

  • 什么是“静态初始化顺序惨败”?

    C++ FAQ 10.14
  • 中对此进行了说明
  • 为什么我认为使用vector会引发惨败?
    vector构造函数可能会使用动态初始化的另一个static-lifetime变量的值。如果是这样,那么在我在代码中使用vector之前,没有什么可以确保vector的变量被初始化的。初始化result(请参见下面的代码)最终可能会在完全初始化vector的依赖项之前调用vector构造函数,从而导致访问未初始化的内存。
  • 反正这段代码是什么样的?
    struct QueryEngine {
      QueryEngine(const char *query, string *result_ptr)
        : query(query), result_ptr(result_ptr) { }
    
      static void AddQuery(const char *query, string *result_ptr) {
        if (pending == NULL)
          pending = new vector<QueryEngine>;
        pending->push_back(QueryEngine(query, result_ptr));
      }
    
      const char *query;
      string *result_ptr;
    
      static vector<QueryEngine> *pending;
    };
    
    vector<QueryEngine> *QueryEngine::pending = NULL;
    
    void Register(const char *query, string *result_ptr) {
      QueryEngine::AddQuery(query, result_ptr);
    }
    
    string result = Register("query", &result);
    
  • 最佳答案

    幸运的是,即使在执行任何其他初始化之前(甚至在相同对象的“true”初始化之前),static对象也被零初始化,因此,您知道在首次调用NULL之前,就已在该指针上设置了Register。1
    现在,就对 vector 进行操作而言,看来(技术上)您可能会遇到这样的问题:

    请注意,尽管在此注释中要求进行同步,但在最后一段中提到了这一点,该段落最终承认static实现的详细信息是允许的。
    话虽如此,似乎标准应该进一步声明用户代码应该避免在静态初始化期间对标准容器进行操作,如果目的是不能保证此类代码的语义。无论哪种方式,我都会认为这是标准的缺陷。应该更清楚。
    1 And it is a NULL pointer, whatever the bit-wise representation of that may be, rather than a blot to all-zero-bits.

    09-10 04:54
    查看更多