0

F# WikiBook のEncapsulating Mutable Stateセクションには、次のコード スニペットがあります。

> let incr =
    let counter = ref 0
    fun () ->
        counter := !counter + 1
        !counter;;

val incr : (unit -> int)

> incr();;
val it : int = 1

> incr();;
val it : int = 2

> incr();;
val it : int = 3

最初は、変更可能な値が呼び出されるたびにcounterインクリメントされるという事実を飲み込むのは簡単に思えました。incr

しかし、しばらく考えた後、私が理解できなかったのは、いつcounterヒープから解放され、counterインクリメントされる前に以前の値をどのように参照しているのかということでした。counter関数スコープ内での生活は、incr複数の関数呼び出しを通じてどのように生き残るのでしょうか?

主な質問は次のとおりです。

  • いつcounterヒープから解放されますか?
  • counterメモリリークじゃない?
4

3 に答える 3

3

この場合、incrは最上位関数です (私の間違いでなければ、静的フィールドとして実装されています)。これは、 という名前の ref セルへの参照を持つクロージャを保持しますcounter。このクロージャが存在する限り、refセルはメモリに保持されます。

現在、この最上位バインディングは、静的な読み取り専用フィールドであるため、ガベージ コレクションを取得することはありません。(C# 用語で)。ただし、有効期間が限られている(ローカルまたはオブジェクト内でバインドされている)ようなクロージャーrefがある場合、クロージャーがガベージ コレクションされると、セルは解放されます。

于 2009-05-03T21:14:35.447 に答える
2

incr に到達できなくなると、カウンターはヒープから解放されます。ガベージ コレクションによるメモリ リークではありません。

于 2009-05-03T20:50:40.370 に答える