2013-03-06 44 views
2

我有一個類定義在main,另一個類(完整的靜態函數/成員)在2個獨立的文件中定義的同一個文件,它崩潰。我想這可能與全局/靜態實例的生命週期有關。看起來在ctor中,靜態成員尚未初始化,並且可能在退出時發生靜態成員在第一個實例被破壞之前被釋放。 這裏是測試代碼:C++ globlal/stack實例ctor/dtor崩潰時調用靜態函數

//testh.h 
    #include <map> 
    class Sc { 
    public: 
     static void insert(); 
     static void out(); 

    private: 
     static std::map<int, int> map_; 
    }; 

    //testcpp.cpp 
    #include "testh.h" 
    #include <iostream> 
    std::map<int, int> Sc::map_; 

    void Sc::insert() { 
     map_.insert(std::make_pair(2,3)); 
    } 

    void Sc::out() { 
     for(auto m : map_) { 
      std::cout << m.first << ' ' << m.second << '\n'; 
     } 
    } 

    //main.cpp 
    #include "testh.h" 
    class Nc { 
    public: 
     Nc() { 
      Sc::insert(); 
      Sc::out(); 
     } 
     ~Nc() { 
      Sc::insert(); 
      Sc::out(); 
     } 
    }; 

    Nc nc; 
    int main() { 

     system("pause"); 
     return 0; 
    } 

這裏有上述代碼的一些奇怪的行爲:

如果我更換staic成員爲int,它不會崩潰,所以我想可能有問題的std ::地圖?

如果我把所有的代碼放到main.cpp中,它不會崩潰,但是不會產生相同的代碼嗎?

如何解決這個問題如果我不想做動態分配(新)?

+0

你有兩個'class Sc',一個在main.cpp中另一個在testh.h中? – billz 2013-03-06 08:29:03

+0

我可以保證std中沒有任何問題。 – 2013-03-06 08:29:44

+0

@billz它是main.cpp中的另一個類Nc,testcpp.cpp/testh.h中的Sc – Frahm 2013-03-06 08:30:57

回答

7

的問題是,你不知道什麼順序次的全局變量將在構建:

// test.cpp 
std::map<int, int> Sc::map_; 

//main.cpp 
Nc nc; 

因爲這些都是在不同的編譯單元該標準不保證它們將被創建的順序。因此,如果首先創建nc,那麼嘗試使用Sc::map_ w生病失敗(並且nc確實通過它對靜態調用的使用)。

當你把全局到一個文件:

//main.cpp 
std::map<int, int> Sc::map_; 
Nc nc; 

然後纔能有保證。這是聲明的順序。所以只要你先輸入Sc::map_就可以了。

有一個簡單的方法來解決這個問題::

替換此:

private: 
    static std::map<int, int> map_; 
}; 

有了:

private: 
    static std::map<int, int>& getMap() 
    { 
     static std::map<int, int> instance; 
     return instance; 
    } 
}; 

但真正的問題是,你使用的是全局可變狀態(全局變量)。儘量不要使用它們。它將您的代碼緊密綁定到globl狀態。您應該通過參數或通過知道如何檢索狀態的對象將狀態傳遞給方法。

+3

我正要鏈接:http://www.parashift.com/c++-faq/static-init-order.html :) – 2013-03-06 08:37:08

+0

所以有什麼辦法來確保靜態成員是在流程結束時被摧毀? – Frahm 2013-03-06 08:40:47

+0

靜態成員總是被正確銷燬。在主退出後,「靜態存儲持續時間」對象按照創建的相反順序銷燬。 – 2013-03-06 08:41:30