【问题标题】:c++ globlal/stack instance ctor/dtor crashing when call static functionc++全局/堆栈实例ctor/dtor在调用静态函数时崩溃
【发布时间】:2013-03-06 08:25:13
【问题描述】:

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

    //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::map 可能有问题?

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

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

【问题讨论】:

  • 你有两个class Sc,一个在main.cpp另一个在testh.h?
  • 我可以保证std中没有任何问题。
  • @billz 这是 main.cpp 中的另一个类 Nc,testcpp.cpp/testh.h 中的 Sc
  • testcpp.cpp 中没有析构函数。这可能是一个原因吗?也许摧毁地图会有所帮助。
  • @lost_with_coding map_ 不是指针,如何销毁它?它是静态的,会自动回收

标签: c++ static-members


【解决方案1】:

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

这个

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

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

【讨论】:

  • 那么有没有办法确保静态成员在进程结束时被销毁?
  • 静态成员总是被正确销毁。 “静态存储持续时间”对象在主退出后按创建的相反顺序销毁。
  • @BЈовић:是的。像往常一样,parashift 完全没用。因为它没有告诉您如何正确解决问题。我完全讨厌那个网站,因为它充满了微妙的错误和错误信息。这个问题的解决方案是废话(它会泄漏)。
  • @LokiAstari it does
  • @BЈовић:这是一个糟糕的解决方案。因为它泄漏。因此在我看来是错误的,不是解决方案。
猜你喜欢
  • 1970-01-01
  • 2012-11-12
  • 2023-03-30
  • 1970-01-01
  • 1970-01-01
  • 2010-11-19
  • 1970-01-01
  • 2011-10-08
  • 1970-01-01
相关资源
最近更新 更多