私は、破壊されているオブジェクトのメソッドの呼び出しによって引き起こされる問題を、アプリケーションのクラッシュの原因となる問題を修正しようとしています。私は、次のクラスがあります削除されているオブジェクトの関数の呼び出しを防止する
// Forward declarations
class A;
class B
{
public:
B(A* aPtr) : m_pA(aPtr) { Schedule(); }
~B() { Timer::ref().Cancel(m_TimerId); }
void Schedule();
void Update();
private:
A* m_pA;
int32_t m_TimerId;
}
void B::Schedule()
{
m_TimerId = Timer::ref().Schedule(1000, [this]() { Update(); });
}
void B::Update()
{
m_pA->DoSomething();
}
class A
{
public:
void Create() { m_B = std::make_unique<B>(); }
void DoSomething() {}
private:
std::unique_ptr<B> m_B;
}
基本的にクラスAは、AのBへの生PTRを格納するクラスBにunique_ptr
タイマ、異なるスレッドにおけるランのシングルトンインスタンスを使用して保持し、そのスケジュール関数B ::更新()は1000ミリ秒ごとにそのスレッドで実行する。場合によっては、A
をスタック上のメンバ変数として格納するオブジェクトを破棄すると、A
が破壊されますが、B::Update()
という別のスレッドから呼び出されたクラスB
の中のぶら下がりポインタは、アプリケーションをクラッシュさせます。 nullptr
です。このため、未定義の動作が発生します。
アプリケーションをクラッシュさせないために、これをどのように処理する必要がありますか?明示的に設定するとm_pA = nullptr
; B::~B()
で十分ですか?
なぜ、スレッドはBのメンバーではないのですか? 〜Bはスレッドに参加して、無効なメモリがないことを確認できます。 – UKMonkey
それはなぜでしょうか?タイマー、またはより具体的にはスケジューラーは、グローバル(貧しいデザインの選択肢、シングルトン、bla bla ...)であり、独自のスレッドを持っています... – mezo
'まあまあ、そうでなければ、データのスコープを完全に定義していないために破棄されたオブジェクトを処理するスレッドが原因でクラッシュする – UKMonkey