c++全局/堆栈实例ctor/dtor调用静态函数时崩溃



我在main的同一文件中定义了一个类,在2个单独的文件中定义了另一个类(充满静态函数/成员),它崩溃了。我想这可能与全局/静态实例的生命周期有关。似乎在actor中,静态成员尚未初始化,并且可能发生退出时,静态成员在第一个实例被销毁之前被释放的情况。下面是测试代码:

    //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;
    }

下面是上面代码的一些奇怪的行为:

如果我将静态成员替换为int,它不会崩溃,所以我想std::map可能有问题?

如果我把所有的代码放到main.cpp中,它不会崩溃,但是这些代码不会生成相同的代码吗?

如何解决这个问题,如果我不想做动态分配(新)?

问题是你不知道全局变量的构造顺序:

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

//main.cpp
Nc nc;

因为它们在不同的编译单元中,所以标准不能保证它们被创建的顺序。因此,如果首先创建nc,那么任何使用Sc::map_的尝试都将失败(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;
    }
};

但是真正的问题是你正在使用全局可变状态(全局变量)。尽量不要使用它们。它将代码紧密地绑定到全局状态。您应该将状态传递给带参数的方法,或者通过知道如何检索状态的对象。

最新更新