c++ - 查找 C++ 静态初始化顺序问题

标签 c++ initialization static-order-fiasco

我们在使用 static initialization order fiasco 时遇到了一些问题。 ,并且我正在寻找方法来梳理大量代码以查找可能出现的情况。有关如何有效地做到这一点的任何建议?

编辑:关于如何解决静态初始化顺序问题,我得到了一些很好的答案,但这不是我的问题。我想知道如何查找受此问题影响的对象。在这方面,埃文的回答似乎是迄今为止最好的;我不认为我们可以使用 valgrind,但我们可能有可以执行类似功能的内存分析工具。这只会在给定构建的初始化顺序错误的情况下发现问题,并且顺序可以随着每次构建而改变。也许有一个静态分析工具可以捕捉到这一点。我们的平台是在 AIX 上运行的 IBM XLC/C++ 编译器。

最佳答案

初始化的求解顺序:

首先,这只是一个临时解决方法,因为您有一些全局变量,您正试图摆脱它们但还没有时间(您最终会摆脱它们,不是吗?: -)

class A
{
    public:
        // Get the global instance abc
        static A& getInstance_abc()  // return a reference
        {
            static A instance_abc;
            return instance_abc;
        }
};

这将保证它在首次使用时被初始化并在应用程序终止时被销毁。

多线程问题:

C++11 确实保证这是线程安全的:

§6.7 [stmt.dcl] p4
If control enters the declaration concurrently while the variable is being initialized, the concurrent execution shall wait for completion of the initialization.

然而,C++03 并没有官方保证静态函数对象的构造是线程安全的。所以从技术上讲,getInstance_XXX() 方法必须用临界区来保护。从好的方面来说,gcc 有一个显式补丁作为编译器的一部分,它保证每个静态函数对象即使在存在线程的情况下也只会被初始化一次。

请注意:不要使用 double checked locking pattern尽量避免锁定的成本。这在 C++03 中不起作用。

创作问题:

在创建时,没有问题,因为我们保证它是在使用之前创建的。

破坏问题:

在对象被销毁后访问对象存在潜在问题。仅当您从另一个全局变量的析构函数访问对象时才会发生这种情况(全局,我指的是任何非局部静态变量)。

解决方案是确保您强制执行销毁顺序。
请记住,破坏顺序与构造顺序完全相反。所以如果你在你的析构函数中访问对象,你必须保证对象没有被销毁。为此,您必须确保在构造调用对象之前完全构造该对象。

class B
{
    public:
        static B& getInstance_Bglob;
        {
            static B instance_Bglob;
            return instance_Bglob;;
        }

        ~B()
        {
             A::getInstance_abc().doSomthing();
             // The object abc is accessed from the destructor.
             // Potential problem.
             // You must guarantee that abc is destroyed after this object.
             // To guarantee this you must make sure it is constructed first.
             // To do this just access the object from the constructor.
        }

        B()
        {
            A::getInstance_abc();
            // abc is now fully constructed.
            // This means it was constructed before this object.
            // This means it will be destroyed after this object.
            // This means it is safe to use from the destructor.
        }
};

关于c++ - 查找 C++ 静态初始化顺序问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/335369/

相关文章:

c++ - 需要建议

c++ - 堆已通过代码在多个地方损坏

c++ - 是否可以使用 std::unique_ptr 来管理 DLL 资源?

c++ - 为什么我不能使用引用类型作为容器类型的值类型?

c++ - 静态顺序初始化失败,iostream 和 C++11

c - 这段代码有错误吗?如果有的话,在哪里

java - 如何通过构造初始化HashSet值?

javascript - 为什么我不能将调用日期对象方法的结果存储在变量中

c++ - C++ 库中静态 STL 容器的双重初始化

autotools - 在 Autoconf 测试中编译多个源文件