Span<T> の GC 保護について

2024/03/24に公開

https://annulusgames.com/blog/span-and-memory/

を読みながら Span の勉強をしている。 → ログ https://zenn.dev/ongaeshi/scraps/cfa2c0fae857ab

static Span<int> ReturnSpan()
{
    // こっちはエラーだけど
    // Span<int> stackSpan = stackalloc int[10];
    // return stackSpan;

    // これは OK
    Span<int> arraySpan = new int[10].AsSpan(3, 4);
    return arraySpan;
}

static void ReturnNewSpanTest()
{
    var span = ReturnSpan();
    Console.WriteLine(span.Length);
}

このときに int[10] の先頭配列のポインタを Span は押さえていないのにちゃんと GC 保護されるのかが気になったので調べた。

結論: マネージドポインタだから正しく保護される

下のページの「管理下ポインタ(Managed Pointer)の特徴」の項目に書いてあった。

https://atmarkit.itmedia.co.jp/fdotnet/dotnetdeepdive/dotnetdeepdive02/dotnetdeepdive02_01.html

●管理下ポインタが次の場所をポイントしている

  • メソッド引数、ローカル変数、ボックス化された値型
  • インスタンス・フィールド
  • 静的フィールド
  • 配列の要素(と最終要素の次の要素)

ここで配列の要素が含まれているときにちゃんと追跡できることが保証されている。

配列の要素だから OK。また Span は ref 構造体なのでスタック以外に乗らないことも保証されている。

ChatGPT との会話ログ

Discussion