查找C ++静态初始化顺序问题 [英] Finding C++ static initialization order problems

查看:173
本文介绍了查找C ++静态初始化顺序问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们遇到了静态初始化顺序fiasco 的问题,我正在寻找方法梳理整个大量的代码,以找到可能的情况。有关如何有效地执行此操作的任何建议?

We've run into some problems with the static initialization order fiasco, and I'm looking for ways to comb through a whole lot of code to find possible occurrences. Any suggestions on how to do this efficiently?

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

I'm getting some good answers on how to SOLVE the static initialization order problem, but that's not really my question. I'd like to know how to FIND objects that are subject to this problem. Evan's answer seems to be the best so far in this regard; I don't think we can use valgrind, but we may have memory analysis tools that could perform a similar function. That would catch problems only where the initialization order is wrong for a given build, and the order can change with each build. Perhaps there's a static analysis tool that would catch this. Our platform is IBM XLC/C++ compiler running on AIX.

推荐答案

解决初始化顺序:



首先,这只是一个临时的工作,因为你有全局变量,你试图摆脱,但只是还没有时间(你要摆脱他们最终aren' t你?: - )

Solving order of initialization:

First off, this is just a temporary work-around because you have global variables that you are trying to get rid of but just have not had time yet (you are going to get rid of them eventually aren't you? :-)

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

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

This will guarantee that it is initialised on first use and destroyed when the application terminates.

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

C++11 does guarantee that this is thread-safe:


§6.7[stmt.dcl] p4

如果控制输入声明在初始化变量的同时,并发执行将等待初始化完成。

§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.

em> 正式保证静态函数对象的构造是线程安全的。所以技术上, getInstance_XXX()方法必须用临界区保护。在明亮的一面,gcc有一个显式的补丁作为编译器的一部分,保证每个静态函数对象只有初始化一次,即使在线程存在。

However, C++03 does not officially guarantee that the construction of static function objects is thread safe. So technically the getInstance_XXX() method must be guarded with a critical section. On the bright side, gcc has an explicit patch as part of the compiler that guarantees that each static function object will only be initialized once even in the presence of threads.

请请注意:不要使用双重锁定锁定模式尝试避免锁定。这在C ++ 03中不起作用。

Please note: Do not use the double checked locking pattern to try and avoid the cost of the locking. This will not work in C++03.

创建时没有问题

在对象被破坏后访问对象的问题。这只会发生,如果你从另一个全局变量的析构函数访问对象(全局,我指的是任何非本地静态变量)。

There is a potential problem of accessing the object after it has been destroyed. This only happens if you access the object from the destructor of another global variable (by global, I am referring to any non-local static variable).

解决方案是请确保强制销毁顺序。

请记住销毁顺序与构造顺序的确切相反。所以如果你访问你的析构函数中的对象,你必须保证对象没有被销毁。要做到这一点,你必须保证对象在构造调用对象之前完全构造。

The solution is to make sure that you force the order of destruction.
Remember the order of destruction is the exact inverse of the order of construction. So if you access the object in your destructor, you must guarantee that the object has not been destroyed. To do this, you must just guarantee that the object is fully constructed before the calling object is constructed.

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 ++静态初始化顺序问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆