問題描述
我們在 靜態初始化順序方面遇到了一些問題慘敗,我正在尋找方法來梳理大量代碼以查找可能出現的情況.關于如何有效地做到這一點有什么建議嗎?
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
{
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.
但是,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
{
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++靜態初始化順序問題的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,也希望大家多多支持html5模板網!