Finding C++ static initialization order problems(查找C++静态初始化顺序问题)


我们在 静态初始化顺序方面遇到了一些问题惨败,我正在寻找方法来梳理大量代码以查找可能出现的情况.关于如何有效地做到这一点有什么建议吗?

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?

关于如何解决静态初始化顺序问题,我得到了一些很好的答案,但这并不是我真正的问题.我想知道如何查找受此问题影响的对象.到目前为止,埃文的回答似乎是最好的;我不认为我们可以使用 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.




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

但是,C++03官方保证静态函数对象的构造是线程安全的.所以从技术上讲,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.

请注意:不要使用双重检查锁定模式a> 尽量避免锁定的成本.这在 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.


On creation, there are no problems because we guarantee that it is created before it can be used.


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
        static B& getInstance_Bglob;
            static B instance_Bglob;
            return instance_Bglob;;

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

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




Algorithm to convert RGB to HSV and HSV to RGB in range 0-255 for both(将 RGB 转换为 HSV 并将 HSV 转换为 RGB 的算法,范围为 0-255)
How to convert an enum type variable to a string?(如何将枚举类型变量转换为字符串?)
When to use inline function and when not to use it?(什么时候使用内联函数,什么时候不使用?)
Examples of good gotos in C or C++(C 或 C++ 中好的 goto 示例)
Significance of ios_base::sync_with_stdio(false); cin.tie(NULL);(ios_base::sync_with_stdio(false) 的意义;cin.tie(NULL);)
Is TCHAR still relevant?(TCHAR 仍然相关吗?)