亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

查找C+靜態初始化順序問題

查找C+靜態初始化順序問題

C++
慕沐林林 2019-07-06 15:49:30
查找C+靜態初始化順序問題我們遇到了一些問題靜態初始化順序失敗,我正在尋找一種方法來梳理大量的代碼,以找到可能出現的情況。對于如何有效地做到這一點,有什么建議嗎?編輯:關于如何解決靜態初始化順序問題,我得到了一些很好的答案,但這并不是我的問題。我想知道如何找到受這個問題影響的對象。在這方面,Evan的回答似乎是迄今為止最好的;我不認為我們可以使用valrun,但是我們可能有一些內存分析工具可以執行類似的功能。這只會捕獲問題,只有當初始化順序對給定的構建是錯誤的,并且順序可以隨每個構建而改變。也許有一個靜態分析工具能捕捉到這一點。我們的平臺是運行在AIX上的IBMXLC/C+編譯器。
查看完整描述

3 回答

?
慕婉清6462132

TA貢獻1804條經驗 獲得超2個贊

解決初始化順序:

首先,這只是一個暫時的解決方案,因為您有一些全局變量,您正試圖擺脫這些變量,但只是還沒有時間(您最終會處理掉它們,不是嗎?:-)

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
如果在初始化變量時控件同時輸入聲明,則并發執行應等待初始化完成。

然而,C+03確實正式保證靜態函數對象的構造是線程安全的。所以嚴格來說getInstance_XXX()方法必須用關鍵部分來保護。好的一面是,GCC有一個顯式的補丁作為編譯器的一部分,它保證每個靜態函數對象只初始化一次,即使在線程存在的情況下也是如此。

請注意:不要使用雙重檢查鎖定模式以避免鎖定的成本。這在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.
        }};


查看完整回答
反對 回復 2019-07-06
?
BIG陽

TA貢獻1859條經驗 獲得超6個贊

根據編譯器的不同,可以在構造函數初始化代碼中放置斷點。在Visualc+中,這是_initterm函數,給出要調用的函數列表的開始和結束指針。

然后進入每個函數以獲得文件和函數名(假設您已經編譯了調試信息)。一旦您有了名稱,就退出函數(備份到_initterm)并繼續到_initterm出口。

這給了你靜態初始化器,不僅僅是代碼中的那些-這是獲取詳盡列表的最簡單方法。你可以過濾掉那些你無法控制的(比如第三方庫中的那些)。

這一理論適用于其他編譯器,但函數的名稱和調試器的功能可能會發生變化。


查看完整回答
反對 回復 2019-07-06
  • 3 回答
  • 0 關注
  • 393 瀏覽

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號