2

メインの同じファイルで定義されたクラスと、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 に入れるとクラッシュしませんが、これらは同じコードを生成しませんか?

動的割り当て(新規)を行いたくない場合、この問題を解決するにはどうすればよいですか?

4

1 に答える 1

8

問題は、グローバル変数がどの順序で構築されるかがわからないことです。

これ

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

この

//main.cpp
Nc nc;

これらは異なるコンパイル単位にあるため、標準はそれらが作成される順序を保証しません。したがって、nc最初に作成された場合、使用の試みSc::map_は失敗します(そしてnc、スタティックへの呼び出しを介してこれを使用します)。

グローバルを1つのファイルに入れる場合:

//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状態に緊密にバインドします。パラメータを使用してメソッドに状態を渡すか、状態を取得する方法を知っているオブジェクトを介して状態を渡す必要があります。

于 2013-03-06T08:34:04.287 に答える