はじめに:
最近の議論で、マップ エントリを削除するとメモリ リークが発生するという問題が提起されました。ポインタのスライスはメモリ リークを引き起こす可能性があります。この質問はその調査をマップに拡張し、特にポインタを保持しているマップからエントリを削除すると同様の動作が発生するかどうかを調べます。
実装の確認:
この主張の真実性を判断するには、 Go のランタイムでマップを削除するためのソース コード (runtime/hashmap.go (関数 mapdelete())) を調べてみましょう。検査の結果、キーと値の両方が削除時にクリアされることがわかります (#600、#602)。
ゼロ化の影響:
これらの値をクリアすると、マップと尖った物体。これにより、値自体がポインターであっても、マップはそれらを参照しなくなります。その結果、他の参照がない場合、ポイントされたオブジェクトはガベージ コレクションの対象になります。
実際の例:
この動作を検証するために、テスト ケースを構築してみましょう:
<code class="go">type point struct { X, Y int } var m = map[int]*point{} func main() { fillMap() delete(m, 1) runtime.GC() time.Sleep(time.Second) fmt.Println(m) } func fillMap() { p := &point{1, 2} runtime.SetFinalizer(p, func(p *point) { fmt.Printf("Finalized: %p %+v\n", p, p) }) m[1] = p fmt.Printf("Put in map: %p %+v\n", p, p) }</code>
出力:
Put in map: 0x1040a128 &{X:1 Y:2} Finalized: 0x1040a128 &{X:1 Y:2} map[]
この例では、ポインター値 (p) がマップに入れられ、ガベージ コレクション時に呼び出されるようにファイナライザーが設定されます。マップからエントリを削除し、ガベージ コレクションを強制した後、ファイナライザーが呼び出され、ポインターが実際にマップから削除されたことが証明されます。
結論:
ソース コードに基づく分析と実際の例から、ポインタのマップからエントリを削除してもメモリ リークは発生しないと結論付けることができます。 Go ランタイムは、クリアされた値をゼロにすることで適切なガベージ コレクションを保証し、他の参照が存在しない場合でも、ポイントされたオブジェクトを再利用できるようにします。
以上がマップ エントリを削除すると、ポインタを保持しているときにメモリ リークが発生しますか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。