2016-11-03 14 views
6

私は彼が例around 37 minutes inを与えているハーブサッターのCppCon 2016話を、見てきた、このような何か:C++でコールバック地獄とは何ですか?なぜメモリがリークしますか?

void f(shared_ptr<T> & ptr) 
{ 
    obj.on_draw([=]() { ... } 
} 

彼はそれから言う、

私はそれがコールバック地獄と呼ばれる聞きましたガベージコレクトポインタ であることを起こるが、それは強力な所有者 - - 、あなたはコールバックを登録して どこに強力な所有者を持っているが、その後、あなたはそれを取り除くことはありません飽きない、 だけで永遠に、今そこに格納されますオブジェクトは決して消えません。

だから、彼はコールバック地獄と呼ばれ、オブジェクトをリークします。 しかし、私はこのコードに何が間違っているのか、それが漏れる理由はよく理解していません。誰かが私にこれを説明できますか?

私はstackoverflowで他の回答を見てきましたが、それらはすべて並行性に関するものです。ハーブサッターが話している何

+0

は、メモリの所有権について話す必要があります。 Cにはガベージコレクタがないので、割り当てられたオブジェクトをいつ/誰が解放しなければならないかを知ることは難しいです。しかし、 'unique_ptr'は役に立ちます。 –

+0

公開されている場合は、トークをリンクしてください。それが良いかどうか、プレゼンテーションのどのスライド#または何時を言うか。 –

+0

@RawN:それは話題ではなく、サッター博士が誰かが答えを出すことなく、話全体を見つけて見ていないと言っていただけで十分ではありません。 –

答えて

5

循環参照です。彼は、リソースが「アップに達した」というコードに渡されていない階層システムを、促進

レイヤ1は、 - (以下と)、レイヤ2からのリソースとオブジェクト

レイヤ2を所有 - Can`tを持っていますレイヤー1オブジェクトへの強力な参照

これが保証するところは、依存関係のグラフが円にならないことです。したがって、レイヤ1がすべてのレイヤ2オブジェクトを解放すると、すべてのリソースが破棄されます。 なぜこれが重要なのですか:C++ Stdライブラリからのリソースは循環参照を扱うことができません(ref-countingすることはできません)。objにはobj bとobj bの強い参照があり、 objに、彼らは決して解放されません。

醜いthruthは円がおそらく異なる作者のソフトウェア・モジュールによって、複数の参照を介していけば、これも問題であるということです。レイヤーのようなスキームがなければ、コードを見て、「これが私が呼び出しているオブジェクトを参照することはありません」と言うことはできません。 Herb Sutterは、実装がわからない限り、リソースを有効に保つ可能性のある関数を決して呼び出さないでください。

これは、あなたがそれを行うべきではありませんと言ってませんが、一連のルールに従うならば、あなたは、システムの徹底的なの残りの部分を知らなくても、レイヤごとに、あるいは、ファイルごとのコードを確認することができます。それ以外の場合は、関数(on_draw)が取ることのできるすべての可能なパスを見つける必要があります。循環的な依存関係が発生する可能性があるかどうかを確認しなければなりません。それはちょっと型システム(おそらくわずかに低いレベルからインターフェイスを許可しない)回避、およびコールバックが何かを行う可能性があるので、そのコンテキストにおいて

「コールバック地獄」は、特に問題です。

コールバックではなく、プレーンポインタを使用し、その後、リソースへの参照を保存するdoesntの場合、これは明示的に彼が漏れる心配する必要があるdoes notの呼び出し側に述べています。今も将来もそうではありません。

関連する問題