最後に、デストラクタを二重に呼び出すことによって引き起こされた非常に奇妙なバグを追跡しました。ここでバグを再現する最小限のコードは次のとおりです。shared_ptrを使用すると奇妙なダブルデストラクタコール
#include <iostream>
#include <memory>
#include <set>
class cEventSystem {
public:
cEventSystem() {
std::cout << "constructor: " << this << std::endl;
}
~cEventSystem() {
std::cout << "destructor: " << this << std::endl;
}
};
class cSubscriber {
public:
cSubscriber(cEventSystem& eventSystem) : eventSystem(eventSystem) {}
virtual ~cSubscriber() {}
virtual void onEvent() = 0;
protected:
cEventSystem& eventSystem;
};
class cTileBrowser: public cSubscriber {
public:
cTileBrowser(cEventSystem eventSystem) : cSubscriber(eventSystem) {}
void onEvent() {}
};
class cGui: public cSubscriber {
public:
cGui(cEventSystem& eventSystem) : cSubscriber(eventSystem) {
tileBrowser = std::make_shared<cTileBrowser>(eventSystem);
}
void onEvent() {}
std::shared_ptr<cTileBrowser> tileBrowser;
};
int main() {
cEventSystem eventSystem;
cGui gui(eventSystem);
}
出力は次のとおりです。
constructor: 0x7fffffffe67f
destructor: 0x7fffffffe2df
destructor: 0x7fffffffe67f
あなたが最初のデストラクタが不要であり、それがで構築されていなかった別のオブジェクトで呼び出される見ることができるようにすべて(住所は違う)、私の実際のコードでは住所は十分に近く、私がイベントシステムに持っているコンテナを壊す。
デバッグは、そのデストラクタコールを引き起こすmake_sharedであることを示しています。
この不要なデストラクタコールはどのような原因で削除されますか? g ++ 4.7とC++ 11フラグを使用します。
通常は(90%の時間)は、segfaultsの原因となる実際のコードで自分のイベントシステムコンテナを破損しますが、まれに破損せずすべてが機能します。
男、あなたはヒーローです、それは今私の本当のコードで動作します!しかし、なぜ一時的なコピーがそれがメモリ内の私のデータを壊すことができないほど安全でないのですか?私はほとんどいつも参照(これは間違いだった)によって渡すが、少なくとも私には奇妙に思える。 – user1873947
@ user1873947、コピーコンストラクタはコンパイラによって生成されているため、おそらく間違ったことをしています。例えばポインタのコピーを作成し、デストラクタがそれを削除すると、元のオブジェクトにぶら下がったポインタが残ってしまいます。 –
@Mark Ransomそれです。私の実際のコードでは、私はポインタのセットを持っています。 – user1873947