2015-10-16 11 views
6

巡回グラフで使用されたとき、私はちょうど私が説明することはできませんSystem.Threading.ThreadLocal<T>に関するガベージコレクタのこの奇妙な行動」に出会いました。通常の状況では、ThreadLocal<T>インスタンスは、オブジェクトが循環オブジェクトグラフの一部である場合を除いて、適切に配置されていなくても、スコープから外れるとガベージコレクションされます。メモリリークのThreadLocal <T>が

次の例では、問題を示しています。

public class Program 
{ 
    public class B { public A A; } 
    public class A { public ThreadLocal<B> LocalB; } 

    private static List<WeakReference> references = new List<WeakReference>(); 

    static void Main(string[] args) { 
     for (var i = 0; i < 1000; i++) 
      CreateGraph(); 

     GC.Collect(); 
     GC.WaitForPendingFinalizers(); 
     GC.Collect(); 
     GC.WaitForPendingFinalizers(); 

     // Expecting to print 0, but it prints 1000 
     Console.WriteLine(references.Count(c => c.IsAlive)); 
    } 

    static void CreateGraph() { 
     var a = new A { LocalB = new ThreadLocal<B>() }; 
     a.LocalB.Value = new B { A = a }; 
     references.Add(new WeakReference(a)); 

     // If either one of the following lines is uncommented, the cyclic 
     // graph is broken, and the programs output will become 0. 
     // a.LocalB = null; 
     // a.LocalB.Value = null; 
     // a.LocalB.Value.A = null; 
     // a.LocalB.Dispose(); 
    } 
} 

Disposeを呼び出していないことDisposeが呼び出されていない場合でも、良い習慣ではありませんが、それは最終的に(ファイナライザを呼び出すことによって)リソースをクリーンアップするためにCLRのデザインだが。

なぜThreadLocal振る舞いは、この点で異なって行い、適切に巡回グラフの場合に配置されていないときに、メモリリークを引き起こす可能性がありますか?これは設計によるものですか?もしそうなら、これはどこに文書化されていますか?または、これはCLRのGCのバグですか? (.NET 4.5でテスト)

+0

[David Kean](https://twitter.com/davkean)はこれがバグであることを確認しました。 – Steven

+0

[クリック](https://mobile.twitter.com/davkean/status/655067698511024128)。 – Steven

答えて

0

MicrosoftのDavid Keanconfirmed

+0

正確なツイート/問題へのリンクはありますか?オリジナルのコメントは去年の10月からのものだったので、ここでは文脈は少し失われています。 –

+0

@JeffDammeyer私は自分の答えをリンクで更新しました。 – Steven

+0

つぶやきは理論的に質問に答えるかもしれませんが、ここではツイートの重要な部分を含めることが望ましいです(// meta.stackoverflow.com/q/8259)。これは、Twitterユーザーが(大学/業界で)一部のユーザーに対してブロックされている可能性があるためです。詳細は[このメタポスト](http://meta.stackoverflow.com/a/313037/4099593)をご覧ください。 –

-3

あなたはDisposeを呼び出さないという理由があります。ガベージコレクタは、最後の手段としてファイナライザを持つオブジェクトのみをクリーンアップします。これは実際にはバグであることを

+2

そして、「TheadLocal 」は実際にはファイナライザを持っています。 – Steven