これは別のプロジェクトで発生した問題を単純化したものです。要素をセットから削除するときに下付き文字
は、私は以下のクラスがあるとしましょう:
class MyClass {
public:
MyClass() {
std::cout << "MyClass constructed\n";
Instances().insert(this);
}
~MyClass() {
std::cout << "MyClass destructed\n";
Instances().erase(this);
}
static std::unordered_set<MyClass*>& Instances() {
static std::unordered_set<MyClass*> _instances;
return _instances;
}
};
それはそれは、クラスの既存のインスタンスを追跡するために使用する静的unordered_set
を持っています。インスタンスが構築されると、そのアドレスがセットに追加されます。インスタンスが破棄されると、そのアドレスがセットから削除されます。
は今、私はMyClass
のインスタンスを含むshared_ptr
秒のvector
を持つ別のクラスを持っている:
struct InstanceContainer {
std::vector<std::shared_ptr<MyClass>> instances;
};
ここでのキーポイントはmain
上記のこのクラスのグローバルインスタンスが存在することです。 main
のクラスを宣言しても問題は発生しないため、これは問題の一部と考えられます。
main
の内部では、私は(と言うInstanceContainer
のグローバルインスタンスがcontainer
と呼ばれている)次のようにします。プログラムが終了するまで、私は読み取りアクセス違反(「ベクトル添字を得るとき
container.instances.emplace_back(std::shared_ptr<MyClass>(new MyClass));
すべては、罰金です範囲外です。)Instances().erase(this)
がMyClass
のデストラクタで実行されます。
_instances
からインスタンスを複数回消去しようとしていた可能性があります(したがって、cout
) - しかし、コンストラクタは一度だけ呼び出され、デストラクタは一度だけ呼び出されます。私はこれが起こるとき、_instances.size()
が0
に等しいことがわかった。奇妙なことは、erase
を呼び出す前は0
と等しいことです。何かがセットから消去される前に、それは空ですか?
私の理論は、これは、プログラムが終了するとオブジェクトが破壊される順序と関係しているということです。おそらく、静的な_instances
は、MyClass
のデストラクタが呼び出される前に解放されています。
私は、誰かがこれについていくつかの光を当てて、それが起こっているかどうかを確かめることができると考えていました。
私の回避策は、消去しようとする前に_instances.size()
が0
であるかどうかを確認することです。これは安全ですか?そうでない場合は、他に何ができますか?
重要な場合は、MSVCを使用しています。 executable exampleです