2013-03-06 45 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