Как память не закреплена в памяти <T>.Span? - PullRequest
1 голос
/ 14 марта 2019

Я считаю, что следующие две части кода должны быть эквивалентны:

// first example
string s = "Hello memmory";
ReadOnlyMemory<char> memory = s.AsMemory();
using (MemoryHandle pin = memory.Pin())
{
    Span<char> span = new Span<char>(pin.Pointer, 1);
    Console.WriteLine(span[0]);
}

// second example
ReadOnlySpan<char> span2 = memory.Span;
Console.WriteLine(span2[0]);

В обоих кодах будет напечатано "H".

Что я не понимаю, так это где открепление памяти во втором примере.

Насколько я понимаю, строка размещается в Heap, MemoryHandle закрепляет ее и создает Span из указателя. MemoryHandle.Dispose открепить память назад.

Я считаю, что memory.Span также должен закрепить память, иначе span не сможет получить доступ к указателю. Но как открепить память во втором примере?

Ответы [ 2 ]

1 голос
/ 14 марта 2019

Последнее предположение неверно: memory.Span не нужно закреплять память, так как сборщик мусора знает о своей базовой ссылке. Закрепление доступно независимо, если вы хотите передать указатель на собственный API.

0 голосов
/ 14 марта 2019

Span живет только в стеке текущего потока метода, а не в куче, поэтому он будет живым, пока вы его там используете.Пока все ясно.

Теперь забавная часть:

Ясная правда в том, что результат memory.Span не закреплен, а только на него ссылаются, используя ref T внутри Span<T>что такое .nets идея управляемых указателей, которые также наблюдаются сборщиком мусора.

До тех пор, пока живет ваша память, ваш промежуток тоже будет работать, и этим ваш промежуток.

Ссылки:

https://msdn.microsoft.com/en-us/magazine/mt814808.aspx?f=255&MSPPError=-2147217396 https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/ref#ref-struct-types

...